Некоторые из элементов 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) {
. . .
... но это не работает. Варум нихт?
ОБНОВИТЬ
С этим кодом внутри части .each вызова $.getJSON():
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
МанМохан Вьяс: Вы имеете в виду так:
}); //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
Нет, последние две попытки тоже не сработали. Я попробовал идею Джозефа Майерса, затем Престола, когда я изменил это:
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, но нахожусь на переднем крае в отношении jQueryUI версии 1.10.3.
ОБНОВЛЕНИЕ 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() {
. . . } // получитьNatlBook()
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
ответ Барваза также не работает для меня; может я неправильно делаю? Основываясь на его ответе, я добавил следующее:
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
Вот как это выглядит (изображение "блок" или "объект" есть, просто оно черное/пустое):
Кстати, «Путешествия Джейми Макфитерса» — потрясающая книга в любом случае, но, возможно, особенно для чтения вашим детям (любой возраст, но, возможно, до подросткового возраста является оптимальным).
.on
):error
events не всплывает в большинстве браузеров, хотя согласно спецификации. Об этом также говорится в.on
документах: Во всех браузерах...error
события (например, , на элементе<img>
) не пузыриться. Такие события не поддерживаются для использования с делегированием... - person apsillers   schedule 22.07.2013