Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added onerror support #59

Closed
wants to merge 3 commits into from

2 participants

@keithchu

It's a pain to diagnose broken images without an onerror state. So added the data-onerror attribute to [data-picture]. It just passes an onerror function to picImg.

@scottjehl
Owner

Hmm. Good idea but maybe it'd be cleaner to make sure one can bind an onerror listener to the data-picture element itself, without using attributes? if the onerror event doesn't bubble already, maybe that's the part to fix here...

@keithchu

@scottjehl True, it's much more intuitive. Doesn't bubble though unfortunately -- it needs to be on the generated img. Made an update.

@scottjehl
Owner

Hey Keith,
If this one is still needed, it might work best to trigger a custom event on the image or data-picture element and let it bubble up. Thoughts?

@scottjehl
Owner

Okay, the new standardized markup approach will include an img element in the source, and picture merely controls its src selection. So.. onerror support should naturally come with that img without us having to add anything to support it. If the spec changes to offer events on the picture element itself, we can reopen this one. Thanks again.

@scottjehl scottjehl closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 32 additions and 15 deletions.
  1. +8 −7 README.md
  2. +24 −8 picturefill.js
View
15 README.md
@@ -15,10 +15,10 @@ Currently, `picturefill.js` compresses to around 498bytes (~0.5kb), after minify
## Markup pattern and explanation
-Mark up your responsive images like this.
+Mark up your responsive images like this.
```html
- <div data-picture data-alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
+ <div data-picture data-alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia" onerror="imgError">
<div data-src="small.jpg"></div>
<div data-src="medium.jpg" data-media="(min-width: 400px)"></div>
<div data-src="large.jpg" data-media="(min-width: 800px)"></div>
@@ -31,20 +31,21 @@ Mark up your responsive images like this.
</div>
```
-Each `div[data-src]` element’s `data-media` attribute accepts any and all CSS3 media queries—such as `min` or `max` width, or even `min-device-pixel-ratio` for HD (retina) displays.
+Each `div[data-src]` element’s `data-media` attribute accepts any and all CSS3 media queries—such as `min` or `max` width, or even `min-device-pixel-ratio` for HD (retina) displays.
### Explained...
Notes on the markup above...
* The `div[data-picture]` element's `alt` attribute is used as alternate text for the generated `img` element.
+* The `div[data-picture]` element's `onerror` attribute is used to call an error function specified in the `HEAD` of your document, of the form `function imgError(el){}`. This is useful for treating broken images. The image element is automatically passed to the error function.
* The `div[data-picture]` element can have any number of `source` elements. The above example may contain more than the average situation would call for.
-* Each `div[data-src]` element must have a `data-src` attribute specifying the image path.
+* Each `div[data-src]` element must have a `data-src` attribute specifying the image path.
* It's generally a good idea to include one source element with no `media` qualifier, so it'll apply everywhere.
* Each `data-src` element can have an optional `media` attribute to make it apply in different media settings. Both media types and queries can be used, like any `media` attribute, but support for media queries depends on the browser (unsupporting browsers fail silently).
* The `matchMedia` polyfill (included in `/external`) is necessary to support the `media` attribute across browsers, even in browsers that support media queries, although it is becoming more widely supported in new browsers.
* The `noscript` element wraps the fallback image for non-JavaScript environments, and including this wrapper prevents browsers from fetching the fallback image during page load (causing unnecessary overhead). Generally, it's a good idea to reference a small image here, as it's likely to be loaded in older/underpowered mobile devices.
-
+
### HD Media Queries
Picturefill natively supports HD(Retina) image replacement. While numerous other solutions exist, picturefill has the added benefit of performance for the user in only getting served one image.
@@ -58,9 +59,9 @@ Picturefill natively supports HD(Retina) image replacement. While numerous othe
<div data-src="medium.jpg" data-media="(min-width: 400px)"></div>
<div data-src="medium_x2.jpg" data-media="(min-width: 400px) and (min-device-pixel-ratio: 2.0)"></div>
<div data-src="large.jpg" data-media="(min-width: 800px)"></div>
- <div data-src="large_x2.jpg" data-media="(min-width: 800px) and (min-device-pixel-ratio: 2.0)"></div>
+ <div data-src="large_x2.jpg" data-media="(min-width: 800px) and (min-device-pixel-ratio: 2.0)"></div>
<div data-src="extralarge.jpg" data-media="(min-width: 1000px)"></div>
- <div data-src="extralarge_x2.jpg" data-media="(min-width: 1000px) and (min-device-pixel-ratio: 2.0)"></div>
+ <div data-src="extralarge_x2.jpg" data-media="(min-width: 1000px) and (min-device-pixel-ratio: 2.0)"></div>
<!-- Fallback content for non-JS browsers. Same img src as the initial, unqualified source element. -->
<noscript>
View
32 picturefill.js
@@ -1,24 +1,26 @@
/*! Picturefill - Responsive Images that work today. (and mimic the proposed Picture element with divs). Author: Scott Jehl, Filament Group, 2012 | License: MIT/GPLv2 */
+/*! modified by kc to support data-onerror */
(function( w ){
-
+
// Enable strict mode
"use strict";
w.picturefill = function() {
var ps = w.document.getElementsByTagName( "div" );
-
+ var pc;
+
// Loop the pictures
for( var i = 0, il = ps.length; i < il; i++ ){
if( ps[ i ].getAttribute( "data-picture" ) !== null ){
var sources = ps[ i ].getElementsByTagName( "div" ),
matches = [];
-
+
// See if which sources match
for( var j = 0, jl = sources.length; j < jl; j++ ){
var media = sources[ j ].getAttribute( "data-media" );
- // if there's no media specified, OR w.matchMedia is supported
+ // if there's no media specified, OR w.matchMedia is supported
if( !media || ( w.matchMedia && w.matchMedia( media ).matches ) ){
matches.push( sources[ j ] );
}
@@ -27,13 +29,27 @@
// Find any existing img element in the picture element
var picImg = ps[ i ].getElementsByTagName( "img" )[ 0 ];
- if( matches.length ){
+ if( matches.length ){
if( !picImg ){
picImg = w.document.createElement( "img" );
picImg.alt = ps[ i ].getAttribute( "data-alt" );
+ pc = ps[ i ];
+
+ if ( picImg.addEventListener ){
+ picImg.addEventListener( "error" , function(){
+ return window[pc.getAttribute("onerror")](picImg);
+ }
+ );
+ }
+ else if ( picImg.attachEvent ) {
+ picImg.attachEvent( "error" , function(){
+ return window[pc.getAttribute("onerror")](picImg);
+ }
+ );
+ }
ps[ i ].appendChild( picImg );
}
-
+
picImg.src = matches.pop().getAttribute( "data-src" );
}
else if( picImg ){
@@ -42,7 +58,7 @@
}
}
};
-
+
// Run on resize and domready (w.load as a fallback)
if( w.addEventListener ){
w.addEventListener( "resize", w.picturefill, false );
@@ -56,5 +72,5 @@
else if( w.attachEvent ){
w.attachEvent( "onload", w.picturefill );
}
-
+
}( this ));
Something went wrong with that request. Please try again.