为什么我的img错误函数会失败?

时间:2022-02-22 15:38:41

Some of the img elements that I am dynamically building may (do) fail. For those cases, I have some code I got from here:Is there a way to programmatically determine that an image link is bad? namely this:

我动态构建的一些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) {
    . . .

...but it's not working. Warum nicht?

…但这不是工作。为什么不?

UPDATE

With this code inside the .each portion of the $.getJSON() call:

$.getJSON()调用的每个部分都包含此代码:

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

...all of the images fail. dataPoint.imghref contains such values as:

…所有的图像都失败了。数据。imghref包含如下值:

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

UPDATE 2

In a nuts hell, I'm adding the "img src" like so:

在一个疯狂的地狱,我添加“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

...so as you can see the img is getting added to the DOM; maybe the fact that I've got height and width properties with my img are the problem...

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

UPDATE 3

ManMohan Vyas: Do you mean like so:

莫汉·维亚斯:你的意思是:

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

?

吗?

UPDATE 4

This:

这样的:

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

...didn't work.

…没有工作。

And FWIW, changing this:

就其价值而言,改变:

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

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

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

...to this:

…:

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

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

...didn't work well (the right stuff populated, but the formatting got all messed up (instead of a solid black background, each section had a black background, but the overall background was silver).

…没有很好地工作(填充了正确的内容,但是格式混乱了(不是纯黑色的背景,每个部分都有黑色的背景,但是整体的背景是银色的)。

UPDATE 5

I just thought of something that may be causing my problem: the images that I'm attempting to show are all jpgs, but the "Image Not Available" image is a png. Does that make a difference? Is that possibly what is causing the rendering engine to get confused? If so, I'll just save the fallback img as a jpg...

我只是想到了一些可能会引起我的问题的东西:我试图显示的图片都是jpg格式的,但是“不可用的图片”是png格式的。这有什么区别吗?这可能是导致渲染引擎混乱的原因吗?如果是的话,我将把后备img保存为jpg格式……

UPDATE 6

Nope, these last two attempts didn't work either. I tried Joseph Myers idea, then Prestauls, as I changed this:

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

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

..to this:

. .:

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

...and no difference. I asked this on the jQuery forum a bit ago: I'm grasping at straws here, but I wonder if having mismatched jQuery/jQueryUI versions could be the problem? In order to support older browsers, I'm still using jQuery 1.9.1, but am on the "bleeding edge" as regards jQueryUI with version 1.10.3.

…和没有区别。我之前在jQuery论坛上问过这个问题:我在这里抓着straws,但我想知道是否有不匹配的jQuery/jQueryUI版本可能是问题所在?为了支持旧的浏览器,我仍然在使用jQuery 1.9.1,但是对于版本1.10.3的jQueryUI,我处于“边缘”。

UPDATE 7

Okay, here's all the pertinent code (some redundant and moot code that will be refactored out has been elided to comply with SO's length limits). The (static) CSS shouldn't matter, right? The only other "code" is Web.config and things of that nature, so none of that should be having an effect on why I can't get the fallback images to display.

好的,这里是所有相关的代码(一些将被重构的冗余和无实际意义的代码被省略以符合SO的长度限制)。(静态)CSS应该不重要,对吧?另一个“代码”是Web。配置和类似的东西,所以这些都不应该影响为什么我不能显示回退图像。

A lot of my failed attempts to get NoImageAvailable.png to display are commented out.

我的很多尝试都失败了。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()

。} / / 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>

UPDATE 8

barvaz's answer also does not work for me; maybe I'm doing it wrong? Based on his answer, this is what I added:

巴瓦兹的回答对我也不起作用;也许我做错了?根据他的回答,我补充如下:

CSS

CSS

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

jQuery

jQuery

0) Added this within the ready handler:

0)在就绪处理程序中添加这个:

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

1) Changed this line:

1)改变这条线:

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

...to this:

…:

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

UPDATE 9

Here's what it looks like (the image "block" or "object" is there, it's just that it's black/blank):

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

为什么我的img错误函数会失败?

BTW, The Travels of Jamie McPheeters is an awesome book at any rate, but perhaps especially to read to your kids (any age, but perhaps pre-teen is optimal).

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

8 个解决方案

#1


2  

use the images loaded plugin

使用图片加载插件

https://github.com/desandro/imagesloaded

https://github.com/desandro/imagesloaded

Leverages jQuery deferred objects awesomeness. This will even handle figuring out whether the image loaded for you, so you dont have to use jQuery.error (TBH, that's not really an appropriate use for that).

使用jQuery延迟对象非常棒。这甚至可以处理是否为您加载图像,因此您不必使用jQuery。错误(TBH,这并不是一个合适的用法)。

#2


6  

Though your explaination is not really clear, the most probable reason is that your <img> tag is not there at the time of calling function $('img').error();

虽然您的解释不是很清楚,但最可能的原因是在调用函数$('img').error()时没有为什么我的img错误函数会失败?标记;

try

试一试

1) create a dynamic image with some id.
2) call error function after putting the the img tag in DOM.

1)使用id创建动态图像2)将img标签放入DOM后调用error函数。

The <img> tag is not bound with the error function, and that is the only reason I can see for not working of your code. now the working sample :

为什么我的img错误函数会失败?标记没有与error函数绑定,这是我能看到的不使用代码的唯一原因。现在工作样本:

html:

html:

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

jQuery Script:

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);

you can check the working fiddle here [http://jsfiddle.net/jyXqw/][1]

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

EDIT *

编辑*

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

EDIT-2 * Check the fiddle, your code seems to be working perfectky fine: http://jsfiddle.net/jYbQx/

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

#3


3  

Concerning your UPDATE 5 , no, there is no reason.

关于你的更新5,没有理由。

You should set error handler before setting attribute src:

在设置属性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);

This is typically how you should do it. Test and see.

这通常是你应该做的。测试看看。

#4


3  

Update based on partial code emailed to me

This is just a guess because all your main scripts and JSON data are missing, so I can't test it. However, these changes will hopefully make it work for you. Please test them!

这只是一个猜测,因为所有的主脚本和JSON数据都丢失了,所以我无法对其进行测试。然而,这些变化有望使它对您有效。请测试!

Right before your code says

在你的代码之前

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

you should add this code exactly as written to your page (I noticed that you had not included this in your page yet):

你应该完全按照写在你的页面上的代码添加这个代码(我注意到你的页面中还没有包含这个代码):

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

Then, inside of your function configLoaded you need to add a second block of code (the new changes to your code are marked by NEW):

然后,在已启用的函数内部,需要添加第二个代码块(对代码的新更改标记为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);
}

This way when your menus load new images, the progress/error handler will be attached again (in case that is needed after the new images are generated). The most important thing of course, is that you include the imagesloaded.pkgd.min.js script code, because the second part of code can do nothing without that.

这样,当菜单加载新图像时,进度/错误处理程序将再次被加载(如果在生成新图像之后需要)。当然,最重要的是要包含imagesload .pkgd.min。js脚本代码,因为代码的第二部分没有它什么都做不了。

Note to the author of the question

All of my suggestions work 100% of the time for me, fully tested like proper Stack Overflow answers should be. Unfortunately, these solutions have not had the chance to be properly incorporated into your code because I am lacking your full code or a self-contained example.

我所有的建议对我来说都是百分百有效的,就像正确的堆栈溢出答案一样。不幸的是,这些解决方案没有机会被恰当地纳入到您的代码中,因为我缺少完整的代码或自包含的示例。

The nutshell that you have given, and the JS Fiddle you provided in another question (with only one line of JavaScript there), and the JS Fiddles from you and other people in various comments are all giving me a clear picture of what your problem is. Yet without enough of your actual code (ideally all of it), I cannot show you how to incorporate the solution properly--it would be like a car mechanic trying to fix a car when the car isn't there, or a math teacher trying to teach someone math problems using hand motions instead of something to write with.

您给出的要点,以及您在另一个问题中提供的JS(只有一行JavaScript),以及您和其他人员在各种评论中的JS Fiddles都让我清楚地了解您的问题是什么。还没有足够的实际代码(理想情况下),我不能向您展示如何将正确的解决方案——它就像一个汽车修理工试图修复一辆车时,车没有,或数学老师在教数学问题的人使用手势代替写字。

I can make any of my solutions work for you, but all I need is a link to your full code which contains the problem, or if for some reason it is confidential, then at minimum a self-contained example. Please see: http://sscce.org

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

Would you mind providing a link to your full code or a self-contained example? I would be happy to modify it so that it works for you. I.e., if these solutions aren't working for you, then there is something else in your code that needs to be fixed, and until that point, I am providing this answer for the benefit of the community.

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

Update with recommended solutions

Add this script to your page:

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

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

That script provides the ability to properly detect all broken images on the page. Read about it here, including a demo which shows exactly the functionality that you are wanting to achieve for your own site: http://desandro.github.io/imagesloaded/

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

Then add one of the following code options to your existing JavaScript. (You may also need to remove all other attempts at detecting image loading errors from your code to make sure there is no conflict.)

然后向现有的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 */
  }
});

This code should work just as well or better, and is even shorter.

这段代码应该可以运行得更好,甚至更短。

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 */
});

General Observations

"In all browsers, the load, scroll, and error events (e.g., on an <img> element) do not bubble. In Internet Explorer 8 and lower, the paste and reset events do not bubble. Such events are not supported for use with delegation, but they can be used when the event handler is directly attached to the element generating the event."

在所有浏览器中,加载、滚动和错误事件(例如,在一个为什么我的img错误函数会失败?元素上)都不会冒泡。在Internet Explorer 8和更低版本中,粘贴和重置事件不会冒泡。此类事件不支持委托使用,但可以在事件处理程序直接连接到生成事件的元素时使用。

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

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

Interpretation: You cannot reliably catch image loading errors with a jQuery selector in a document where HTML content is being generated asynchronously from the jQuery command.

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

Therefore, when registering an error handler for an image (such as replacing it with a "no image available" image), it is important to register the error handler on the image before the image element has been inserted into the DOM or becomes a live document fragment. If your image src exists in a pure JavaScript string, you need to make sure than an onerror handler is specified before that string is converted to a live document fragment. If your image src exists in a JavaScript image object, then it is already too late to specify an error handler--in that case, you must specify the handler before the src.

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

Otherwise, there is a race condition going on after the image element has been inserted into the DOM, and before registering the event handler. An image can return a 404 Not Found very quickly since no image data need to load. If the event handler is not fully attached before the 404 has been detected, then the event handler will not be called.

否则,在将图像元素插入到DOM之后,以及在注册事件处理程序之前,就会发生竞争条件。由于不需要加载图像数据,因此图像可以返回一个不能很快找到的404。如果在检测到404之前没有完全附加事件处理程序,则不会调用事件处理程序。

Having an error image be PNG rather than JPEG does not matter.

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

The way your code is constructed, it forms an HTML string then converts it to a live HTML object by using it as the argument to the jQuery constructor, and only then sets the error handler for the img elements that it contains. This causes the same problem as having HTML source that contains no onerror attribute, and then afterwards trying to set the error handler with a script. The behavior you mention

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

This works for me, just changing the last few lines in your JS Fiddle, and setting the attribute in the HTML string before anything is converted to actual live elements:

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

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

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

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

You indicated that this does not work, but it should (after changing placeholder.jpg and #container to your own values), and a proper diagnosis requires me to see everything in your page, since anything else you are doing could affect why this isn't working for you.

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

Other Options You Have (Updated)

Properly implementing the solution of using an error handler requires you to register the onerror / error event handler before specifying the src of the image in a live document fragment.

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

There are other alternatives, however. For example, after the entire document is loaded, you can make a function which loops through all of the page's image elements, locating those that failed to load, and changing their src attribute.

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

That solution is outlined here:

这一解决办法概述如下:

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

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

I can't guarantee that it will work because as I mentioned, anything else you are doing could affect why something isn't working for you.

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

This method of solving the problem also has a plug-in that may work with your code. https://github.com/desandro/imagesloaded

这种解决问题的方法也有一个插件,可以使用您的代码。https://github.com/desandro/imagesloaded

You can use it like this after first inserting script tags for the plug-in http://desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js into your document:

在第一次插入插件http://desandro.github.io/imagesloaded/imagesload.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 */
  }
});

Again, it is possible that something else you are doing will conflict with this plug-in, but it is definitely worth a try! It works perfectly in my example here:

同样,您正在做的其他事情可能会与这个插件发生冲突,但这绝对值得一试!它在我这里的例子中非常有效:

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

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

Summary

Since image error events don't bubble, a global error tracking function solution is not possible, leaving two general ways of dealing with this problem:

由于图像错误事件不冒泡,因此不可能有全局错误跟踪函数解决方案,因此有两种通用的处理方法:

  1. A local way of individually registering an error handler for each image, preferably before its src is specified, but at minimum before it becomes a live HTML fragment or JavaScript image object. The advantage of this method is that error handling will happen immediately for each image, replacing the broken image icon with your placeholder image as soon as the 404 Not Found is detected.
  2. 为每个图像单独注册一个错误处理程序的本地方法,最好是在指定它的src之前,但至少在它成为一个活的HTML片段或JavaScript图像对象之前。这种方法的优点是,错误处理将立即发生在每个图像上,一旦检测到404错误,就用占位符图像替换损坏的图像图标。
  3. A global way of locating broken images throughout the page. This method has the disadvantages of not immediately fixing broken images (lots of time may be spent loading other large images before finally the broken images will be fixed) and of not working for images which may be added to the page later after the initial loading event happens (e.g., images loaded later from Ajax data), but it has the advantage of working for images which are loaded into the page by various mechanisms, like your hmtlBuilder string, that would require complete re-programming to allow images to individually have error handlers assigned.
  4. 在整个页面中定位破损图像的全局方法。这种方法的缺点是不能立即修复破碎的图像(花很多时间可以加载其他大型图像,最后破碎的图片将被修正)和不工作的图片可能被添加到页面后初始加载事件发生(例如,图片加载后Ajax数据),但是它的优势是在图像加载到页面的各种机制,喜欢你hmtlBuilder字符串,这需要完全的重新编程,使图像能够单独地分配错误处理程序。

The ideal way to solve this problem (which doesn't exist) would be for browsers to "bubble" the image error event into a general document error event, which could be monitored by a single event handler, checking to see if the source of the error event was an img element, and if so, then checking the kind of error and replacing an image not found with the desired placeholder.

理想的方式来解决这个问题(不存在)是浏览器“泡沫”的图像错误事件到一个通用文档的错误事件,这可能是由一个事件处理程序,监控检查错误事件是一个img元素的来源,如果是这样,那么检查的错误和替换图片没有找到所需的占位符。

Once again, I would be happy to help you make one of these two correct solution methods work if you send me a link to your entire page. The specifics of making any JavaScript work with your code requires one to see all of your code since there can be other lurking variables.

再一次,如果您给我发送到整个页面的链接,我很乐意帮助您实现这两种正确的解决方案方法之一。使任何JavaScript与代码一起工作的细节都需要一个人查看所有代码,因为可能存在其他隐藏的变量。

#5


2  

You edit seems to be the issue. Having a fallback should fix your issue

你的编辑似乎是问题所在。有一个退路应该可以解决你的问题

#6


2  

Multiple problems here potentially...

多个问题可能……

Event creation/bubbling

You shouldn't need to bind .error on every img. Instead try this once before you enter your loop:

不需要对每个img都绑定.error。相反,在你进入你的循环之前尝试一次:

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

Due to event bubbling, every parent element of an img fires an error event as well. So theres no need to bind using .error in the loop.

由于事件冒泡,img的每个父元素也会触发一个错误事件。因此无需在循环中使用.error进行绑定。

Next...

下一个……

Using Templates/Avoiding HTML in JS

You don't need to use something like handlebars or underscore's templating language; however you should attempt to at least avoid any html in your JS. It is prone to error. Your img markup (for instance) isn't valid.

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

Try the following for your images:

尝试以下图片:

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

You could start your loop by creating a section:

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

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

Then as you loop you can append to it:

然后当你循环,你可以附加它:

$output.append($img);

This reduces the surface area for messing up. If you want to further reduce the surface area you could use a template language like handlebars.

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

Lastly...

最后……

Image mime types? Network traffic?

What does your network traffic say is returned by the calls to the images? Does it say 200 success? Does it say 400? Open chrome's developer tools -> click the Network tab. Observe the traffic and try to see what it says about your images.

对映像的调用返回了什么网络流量?是不是说200个成功?它说400吗?打开chrome的开发工具——>点击网络标签。观察交通,试着看看它对你的图像有什么影响。

What's the server code? Is it 200? If it is 200 what's the mime type? Did you properly configure S3? Is the image URL being modified from the JSON in some way?

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

#7


2  

I had the same problem. the .error or other delegation methods (attached to the window/document/DOM node) did not work for me on <img> created dynamically after ajax response. My solution is using the onerror attribute inside the <img> tag (w3c standard) that calls a javascript function the removes the image and adds a noImg class to the parent node.

我也有同样的问题。在ajax响应后动态创建的为什么我的img错误函数会失败?上,.error或其他委托方法(附加到窗口/文档/DOM节点)对我不起作用。我的解决方案是在为什么我的img错误函数会失败?标记(w3c标准)中使用onerror属性,该属性调用javascript函数the remove the image并向父节点添加noImg类。

Inside the <img> tag:

在< img >标记:

onerror='replaceEmptyImage($(this))'

replaceEmptyImage function:

replaceEmptyImage功能:

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

In css:

在css中:

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

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

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

#8


1  

.on('error' handler); is available since jQuery 1.7 image loading error don't bubble up and a delegate don't work binding a simple function works and is clean

内(“错误”处理程序);是否可用,因为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);
            });
        });

#1


2  

use the images loaded plugin

使用图片加载插件

https://github.com/desandro/imagesloaded

https://github.com/desandro/imagesloaded

Leverages jQuery deferred objects awesomeness. This will even handle figuring out whether the image loaded for you, so you dont have to use jQuery.error (TBH, that's not really an appropriate use for that).

使用jQuery延迟对象非常棒。这甚至可以处理是否为您加载图像,因此您不必使用jQuery。错误(TBH,这并不是一个合适的用法)。

#2


6  

Though your explaination is not really clear, the most probable reason is that your <img> tag is not there at the time of calling function $('img').error();

虽然您的解释不是很清楚,但最可能的原因是在调用函数$('img').error()时没有为什么我的img错误函数会失败?标记;

try

试一试

1) create a dynamic image with some id.
2) call error function after putting the the img tag in DOM.

1)使用id创建动态图像2)将img标签放入DOM后调用error函数。

The <img> tag is not bound with the error function, and that is the only reason I can see for not working of your code. now the working sample :

为什么我的img错误函数会失败?标记没有与error函数绑定,这是我能看到的不使用代码的唯一原因。现在工作样本:

html:

html:

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

jQuery Script:

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);

you can check the working fiddle here [http://jsfiddle.net/jyXqw/][1]

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

EDIT *

编辑*

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

EDIT-2 * Check the fiddle, your code seems to be working perfectky fine: http://jsfiddle.net/jYbQx/

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

#3


3  

Concerning your UPDATE 5 , no, there is no reason.

关于你的更新5,没有理由。

You should set error handler before setting attribute src:

在设置属性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);

This is typically how you should do it. Test and see.

这通常是你应该做的。测试看看。

#4


3  

Update based on partial code emailed to me

This is just a guess because all your main scripts and JSON data are missing, so I can't test it. However, these changes will hopefully make it work for you. Please test them!

这只是一个猜测,因为所有的主脚本和JSON数据都丢失了,所以我无法对其进行测试。然而,这些变化有望使它对您有效。请测试!

Right before your code says

在你的代码之前

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

you should add this code exactly as written to your page (I noticed that you had not included this in your page yet):

你应该完全按照写在你的页面上的代码添加这个代码(我注意到你的页面中还没有包含这个代码):

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

Then, inside of your function configLoaded you need to add a second block of code (the new changes to your code are marked by NEW):

然后,在已启用的函数内部,需要添加第二个代码块(对代码的新更改标记为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);
}

This way when your menus load new images, the progress/error handler will be attached again (in case that is needed after the new images are generated). The most important thing of course, is that you include the imagesloaded.pkgd.min.js script code, because the second part of code can do nothing without that.

这样,当菜单加载新图像时,进度/错误处理程序将再次被加载(如果在生成新图像之后需要)。当然,最重要的是要包含imagesload .pkgd.min。js脚本代码,因为代码的第二部分没有它什么都做不了。

Note to the author of the question

All of my suggestions work 100% of the time for me, fully tested like proper Stack Overflow answers should be. Unfortunately, these solutions have not had the chance to be properly incorporated into your code because I am lacking your full code or a self-contained example.

我所有的建议对我来说都是百分百有效的,就像正确的堆栈溢出答案一样。不幸的是,这些解决方案没有机会被恰当地纳入到您的代码中,因为我缺少完整的代码或自包含的示例。

The nutshell that you have given, and the JS Fiddle you provided in another question (with only one line of JavaScript there), and the JS Fiddles from you and other people in various comments are all giving me a clear picture of what your problem is. Yet without enough of your actual code (ideally all of it), I cannot show you how to incorporate the solution properly--it would be like a car mechanic trying to fix a car when the car isn't there, or a math teacher trying to teach someone math problems using hand motions instead of something to write with.

您给出的要点,以及您在另一个问题中提供的JS(只有一行JavaScript),以及您和其他人员在各种评论中的JS Fiddles都让我清楚地了解您的问题是什么。还没有足够的实际代码(理想情况下),我不能向您展示如何将正确的解决方案——它就像一个汽车修理工试图修复一辆车时,车没有,或数学老师在教数学问题的人使用手势代替写字。

I can make any of my solutions work for you, but all I need is a link to your full code which contains the problem, or if for some reason it is confidential, then at minimum a self-contained example. Please see: http://sscce.org

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

Would you mind providing a link to your full code or a self-contained example? I would be happy to modify it so that it works for you. I.e., if these solutions aren't working for you, then there is something else in your code that needs to be fixed, and until that point, I am providing this answer for the benefit of the community.

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

Update with recommended solutions

Add this script to your page:

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

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

That script provides the ability to properly detect all broken images on the page. Read about it here, including a demo which shows exactly the functionality that you are wanting to achieve for your own site: http://desandro.github.io/imagesloaded/

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

Then add one of the following code options to your existing JavaScript. (You may also need to remove all other attempts at detecting image loading errors from your code to make sure there is no conflict.)

然后向现有的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 */
  }
});

This code should work just as well or better, and is even shorter.

这段代码应该可以运行得更好,甚至更短。

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 */
});

General Observations

"In all browsers, the load, scroll, and error events (e.g., on an <img> element) do not bubble. In Internet Explorer 8 and lower, the paste and reset events do not bubble. Such events are not supported for use with delegation, but they can be used when the event handler is directly attached to the element generating the event."

在所有浏览器中,加载、滚动和错误事件(例如,在一个为什么我的img错误函数会失败?元素上)都不会冒泡。在Internet Explorer 8和更低版本中,粘贴和重置事件不会冒泡。此类事件不支持委托使用,但可以在事件处理程序直接连接到生成事件的元素时使用。

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

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

Interpretation: You cannot reliably catch image loading errors with a jQuery selector in a document where HTML content is being generated asynchronously from the jQuery command.

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

Therefore, when registering an error handler for an image (such as replacing it with a "no image available" image), it is important to register the error handler on the image before the image element has been inserted into the DOM or becomes a live document fragment. If your image src exists in a pure JavaScript string, you need to make sure than an onerror handler is specified before that string is converted to a live document fragment. If your image src exists in a JavaScript image object, then it is already too late to specify an error handler--in that case, you must specify the handler before the src.

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

Otherwise, there is a race condition going on after the image element has been inserted into the DOM, and before registering the event handler. An image can return a 404 Not Found very quickly since no image data need to load. If the event handler is not fully attached before the 404 has been detected, then the event handler will not be called.

否则,在将图像元素插入到DOM之后,以及在注册事件处理程序之前,就会发生竞争条件。由于不需要加载图像数据,因此图像可以返回一个不能很快找到的404。如果在检测到404之前没有完全附加事件处理程序,则不会调用事件处理程序。

Having an error image be PNG rather than JPEG does not matter.

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

The way your code is constructed, it forms an HTML string then converts it to a live HTML object by using it as the argument to the jQuery constructor, and only then sets the error handler for the img elements that it contains. This causes the same problem as having HTML source that contains no onerror attribute, and then afterwards trying to set the error handler with a script. The behavior you mention

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

This works for me, just changing the last few lines in your JS Fiddle, and setting the attribute in the HTML string before anything is converted to actual live elements:

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

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

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

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

You indicated that this does not work, but it should (after changing placeholder.jpg and #container to your own values), and a proper diagnosis requires me to see everything in your page, since anything else you are doing could affect why this isn't working for you.

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

Other Options You Have (Updated)

Properly implementing the solution of using an error handler requires you to register the onerror / error event handler before specifying the src of the image in a live document fragment.

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

There are other alternatives, however. For example, after the entire document is loaded, you can make a function which loops through all of the page's image elements, locating those that failed to load, and changing their src attribute.

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

That solution is outlined here:

这一解决办法概述如下:

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

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

I can't guarantee that it will work because as I mentioned, anything else you are doing could affect why something isn't working for you.

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

This method of solving the problem also has a plug-in that may work with your code. https://github.com/desandro/imagesloaded

这种解决问题的方法也有一个插件,可以使用您的代码。https://github.com/desandro/imagesloaded

You can use it like this after first inserting script tags for the plug-in http://desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js into your document:

在第一次插入插件http://desandro.github.io/imagesloaded/imagesload.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 */
  }
});

Again, it is possible that something else you are doing will conflict with this plug-in, but it is definitely worth a try! It works perfectly in my example here:

同样,您正在做的其他事情可能会与这个插件发生冲突,但这绝对值得一试!它在我这里的例子中非常有效:

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

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

Summary

Since image error events don't bubble, a global error tracking function solution is not possible, leaving two general ways of dealing with this problem:

由于图像错误事件不冒泡,因此不可能有全局错误跟踪函数解决方案,因此有两种通用的处理方法:

  1. A local way of individually registering an error handler for each image, preferably before its src is specified, but at minimum before it becomes a live HTML fragment or JavaScript image object. The advantage of this method is that error handling will happen immediately for each image, replacing the broken image icon with your placeholder image as soon as the 404 Not Found is detected.
  2. 为每个图像单独注册一个错误处理程序的本地方法,最好是在指定它的src之前,但至少在它成为一个活的HTML片段或JavaScript图像对象之前。这种方法的优点是,错误处理将立即发生在每个图像上,一旦检测到404错误,就用占位符图像替换损坏的图像图标。
  3. A global way of locating broken images throughout the page. This method has the disadvantages of not immediately fixing broken images (lots of time may be spent loading other large images before finally the broken images will be fixed) and of not working for images which may be added to the page later after the initial loading event happens (e.g., images loaded later from Ajax data), but it has the advantage of working for images which are loaded into the page by various mechanisms, like your hmtlBuilder string, that would require complete re-programming to allow images to individually have error handlers assigned.
  4. 在整个页面中定位破损图像的全局方法。这种方法的缺点是不能立即修复破碎的图像(花很多时间可以加载其他大型图像,最后破碎的图片将被修正)和不工作的图片可能被添加到页面后初始加载事件发生(例如,图片加载后Ajax数据),但是它的优势是在图像加载到页面的各种机制,喜欢你hmtlBuilder字符串,这需要完全的重新编程,使图像能够单独地分配错误处理程序。

The ideal way to solve this problem (which doesn't exist) would be for browsers to "bubble" the image error event into a general document error event, which could be monitored by a single event handler, checking to see if the source of the error event was an img element, and if so, then checking the kind of error and replacing an image not found with the desired placeholder.

理想的方式来解决这个问题(不存在)是浏览器“泡沫”的图像错误事件到一个通用文档的错误事件,这可能是由一个事件处理程序,监控检查错误事件是一个img元素的来源,如果是这样,那么检查的错误和替换图片没有找到所需的占位符。

Once again, I would be happy to help you make one of these two correct solution methods work if you send me a link to your entire page. The specifics of making any JavaScript work with your code requires one to see all of your code since there can be other lurking variables.

再一次,如果您给我发送到整个页面的链接,我很乐意帮助您实现这两种正确的解决方案方法之一。使任何JavaScript与代码一起工作的细节都需要一个人查看所有代码,因为可能存在其他隐藏的变量。

#5


2  

You edit seems to be the issue. Having a fallback should fix your issue

你的编辑似乎是问题所在。有一个退路应该可以解决你的问题

#6


2  

Multiple problems here potentially...

多个问题可能……

Event creation/bubbling

You shouldn't need to bind .error on every img. Instead try this once before you enter your loop:

不需要对每个img都绑定.error。相反,在你进入你的循环之前尝试一次:

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

Due to event bubbling, every parent element of an img fires an error event as well. So theres no need to bind using .error in the loop.

由于事件冒泡,img的每个父元素也会触发一个错误事件。因此无需在循环中使用.error进行绑定。

Next...

下一个……

Using Templates/Avoiding HTML in JS

You don't need to use something like handlebars or underscore's templating language; however you should attempt to at least avoid any html in your JS. It is prone to error. Your img markup (for instance) isn't valid.

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

Try the following for your images:

尝试以下图片:

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

You could start your loop by creating a section:

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

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

Then as you loop you can append to it:

然后当你循环,你可以附加它:

$output.append($img);

This reduces the surface area for messing up. If you want to further reduce the surface area you could use a template language like handlebars.

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

Lastly...

最后……

Image mime types? Network traffic?

What does your network traffic say is returned by the calls to the images? Does it say 200 success? Does it say 400? Open chrome's developer tools -> click the Network tab. Observe the traffic and try to see what it says about your images.

对映像的调用返回了什么网络流量?是不是说200个成功?它说400吗?打开chrome的开发工具——>点击网络标签。观察交通,试着看看它对你的图像有什么影响。

What's the server code? Is it 200? If it is 200 what's the mime type? Did you properly configure S3? Is the image URL being modified from the JSON in some way?

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

#7


2  

I had the same problem. the .error or other delegation methods (attached to the window/document/DOM node) did not work for me on <img> created dynamically after ajax response. My solution is using the onerror attribute inside the <img> tag (w3c standard) that calls a javascript function the removes the image and adds a noImg class to the parent node.

我也有同样的问题。在ajax响应后动态创建的为什么我的img错误函数会失败?上,.error或其他委托方法(附加到窗口/文档/DOM节点)对我不起作用。我的解决方案是在为什么我的img错误函数会失败?标记(w3c标准)中使用onerror属性,该属性调用javascript函数the remove the image并向父节点添加noImg类。

Inside the <img> tag:

在< img >标记:

onerror='replaceEmptyImage($(this))'

replaceEmptyImage function:

replaceEmptyImage功能:

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

In css:

在css中:

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

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

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

#8


1  

.on('error' handler); is available since jQuery 1.7 image loading error don't bubble up and a delegate don't work binding a simple function works and is clean

内(“错误”处理程序);是否可用,因为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);
            });
        });