Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>Update based on partial code emailed to me</h2> <p>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!</p> <p>Right before your code says</p> <pre><code>&lt;div id="tabs" class="content-wrapper"&gt; </code></pre> <p>you should add this code exactly as written to your page (I noticed that you had not included this in your page yet):</p> <pre><code>&lt;script src="//desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js"&gt; &lt;/script&gt; </code></pre> <p>Then, inside of your function <code>configLoaded</code> you need to add a second block of code (the new changes to your code are marked by NEW):</p> <pre><code>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); } </code></pre> <p>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 <code>imagesloaded.pkgd.min.js</code> script code, because the second part of code can do nothing without that.</p> <h2>Note to the author of the question</h2> <p>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 <em>into your code</em> because I am lacking your full code or a self-contained example.</p> <p>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 <em>picture</em> 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.</p> <p>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: <a href="http://sscce.org" rel="nofollow noreferrer">http://sscce.org</a> </p> <p>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.</p> <h2>Update with recommended solutions</h2> <p>Add this script to your page:</p> <pre><code>&lt;script src="//desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js"&gt; &lt;/script&gt; </code></pre> <p>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: <a href="http://desandro.github.io/imagesloaded/" rel="nofollow noreferrer">http://desandro.github.io/imagesloaded/</a></p> <p>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.)</p> <pre><code>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 &lt; 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 */ } }); </code></pre> <p>This code should work just as well or better, and is even shorter.</p> <pre><code>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 */ }); </code></pre> <h2>General Observations</h2> <blockquote> <p>"In all browsers, the load, scroll, and error events (e.g., on an &lt;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."</p> <p><a href="http://api.jquery.com/on/" rel="nofollow noreferrer">http://api.jquery.com/on/</a></p> </blockquote> <p>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.</p> <p>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 <code>src</code> exists in a pure JavaScript string, you need to make sure than an <code>onerror</code> handler is specified before that string is converted to a live document fragment. If your image <code>src</code> 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 <code>src</code>.</p> <p>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.</p> <p>Having an error image be PNG rather than JPEG does not matter.</p> <p>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 <em>then</em> sets the <em>error</em> handler for the <code>img</code> elements that it contains. This causes the same problem as having HTML source that contains no <code>onerror</code> attribute, and then afterwards trying to set the error handler with a script. The behavior you mention </p> <p>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:</p> <pre><code>imageError = function(it) { $(it).attr("src","placeholder.jpg"); }; htmlBuilder = htmlBuilder.replace(/&lt;img/g, '&lt;img onerror="imageError(this)"'); var jObject = $(htmlBuilder); $("#container").html(jObject); </code></pre> <p>You indicated that this does not work, but it should (after changing <code>placeholder.jpg</code> and <code>#container</code> 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.</p> <h2>Other Options You Have (Updated)</h2> <p>Properly implementing the solution of using an error handler requires you to register the <code>onerror</code> / <code>error</code> event handler <em>before</em> specifying the <code>src</code> of the image in a live document fragment.</p> <p>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 <code>src</code> attribute.</p> <p>That solution is outlined here:</p> <p><a href="https://stackoverflow.com/a/93017/2188862">https://stackoverflow.com/a/93017/2188862</a></p> <p>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.</p> <p>This method of solving the problem also has a plug-in that <em>may</em> work with your code. <a href="https://github.com/desandro/imagesloaded" rel="nofollow noreferrer">https://github.com/desandro/imagesloaded</a></p> <p>You can use it like this after first inserting script tags for the plug-in <a href="http://desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js" rel="nofollow noreferrer">http://desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js</a> into your document:</p> <pre><code>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 &lt; 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 */ } }); </code></pre> <p>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:</p> <p><a href="http://jsfiddle.net/cookies/xdfjU/15/" rel="nofollow noreferrer">http://jsfiddle.net/cookies/xdfjU/15/</a></p> <h2>Summary</h2> <p>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:</p> <ol> <li>A local way of individually registering an error handler for each image, preferably before its <code>src</code> 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.</li> <li>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 <code>hmtlBuilder</code> string, that would require complete re-programming to allow images to individually have error handlers assigned.</li> </ol> <p>The ideal way to solve this problem (which doesn't exist) would be for browsers to "bubble" the image <code>error</code> 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 <code>img</code> element, and if so, then checking the kind of error and replacing an image not found with the desired placeholder.</p> <p>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.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload