mirror of
https://github.com/danbee/danbarber.me
synced 2025-03-04 08:59:10 +00:00
Update picturefill.
This commit is contained in:
parent
c7b51ffe8c
commit
b6b8ff2e81
@ -1,6 +1,6 @@
|
|||||||
/*! Picturefill - v2.1.0 - 2014-08-20
|
/*! Picturefill - v2.3.1 - 2015-04-09
|
||||||
* http://scottjehl.github.io/picturefill
|
* http://scottjehl.github.io/picturefill
|
||||||
* Copyright (c) 2014 https://github.com/scottjehl/picturefill/blob/master/Authors.txt; Licensed MIT */
|
* Copyright (c) 2015 https://github.com/scottjehl/picturefill/blob/master/Authors.txt; Licensed MIT */
|
||||||
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
|
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
|
||||||
|
|
||||||
window.matchMedia || (window.matchMedia = function() {
|
window.matchMedia || (window.matchMedia = function() {
|
||||||
@ -52,13 +52,28 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
* License: MIT/GPLv2
|
* License: MIT/GPLv2
|
||||||
* Spec: http://picture.responsiveimages.org/
|
* Spec: http://picture.responsiveimages.org/
|
||||||
*/
|
*/
|
||||||
(function( w, doc ) {
|
(function( w, doc, image ) {
|
||||||
// Enable strict mode
|
// Enable strict mode
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
function expose(picturefill) {
|
||||||
|
/* expose picturefill */
|
||||||
|
if ( typeof module === "object" && typeof module.exports === "object" ) {
|
||||||
|
// CommonJS, just export
|
||||||
|
module.exports = picturefill;
|
||||||
|
} else if ( typeof define === "function" && define.amd ) {
|
||||||
|
// AMD support
|
||||||
|
define( "picturefill", function() { return picturefill; } );
|
||||||
|
}
|
||||||
|
if ( typeof w === "object" ) {
|
||||||
|
// If no AMD and we are in the browser, attach to window
|
||||||
|
w.picturefill = picturefill;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If picture is supported, well, that's awesome. Let's get outta here...
|
// If picture is supported, well, that's awesome. Let's get outta here...
|
||||||
if ( w.HTMLPictureElement ) {
|
if ( w.HTMLPictureElement ) {
|
||||||
w.picturefill = function() { };
|
expose(function() { });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,24 +81,37 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
doc.createElement( "picture" );
|
doc.createElement( "picture" );
|
||||||
|
|
||||||
// local object for method references and testing exposure
|
// local object for method references and testing exposure
|
||||||
var pf = {};
|
var pf = w.picturefill || {};
|
||||||
|
|
||||||
|
var regWDesc = /\s+\+?\d+(e\d+)?w/;
|
||||||
|
|
||||||
// namespace
|
// namespace
|
||||||
pf.ns = "picturefill";
|
pf.ns = "picturefill";
|
||||||
|
|
||||||
// srcset support test
|
// srcset support test
|
||||||
pf.srcsetSupported = "srcset" in doc.createElement( "img" );
|
(function() {
|
||||||
pf.sizesSupported = w.HTMLImageElement.sizes;
|
pf.srcsetSupported = "srcset" in image;
|
||||||
|
pf.sizesSupported = "sizes" in image;
|
||||||
|
pf.curSrcSupported = "currentSrc" in image;
|
||||||
|
})();
|
||||||
|
|
||||||
// just a string trim workaround
|
// just a string trim workaround
|
||||||
pf.trim = function( str ) {
|
pf.trim = function( str ) {
|
||||||
return str.trim ? str.trim() : str.replace( /^\s+|\s+$/g, "" );
|
return str.trim ? str.trim() : str.replace( /^\s+|\s+$/g, "" );
|
||||||
};
|
};
|
||||||
|
|
||||||
// just a string endsWith workaround
|
/**
|
||||||
pf.endsWith = function( str, suffix ) {
|
* Gets a string and returns the absolute URL
|
||||||
return str.endsWith ? str.endsWith( suffix ) : str.indexOf( suffix, str.length - suffix.length ) !== -1;
|
* @param src
|
||||||
};
|
* @returns {String} absolute URL
|
||||||
|
*/
|
||||||
|
pf.makeUrl = (function() {
|
||||||
|
var anchor = doc.createElement( "a" );
|
||||||
|
return function(src) {
|
||||||
|
anchor.href = src;
|
||||||
|
return anchor.href;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut method for https://w3c.github.io/webappsec/specs/mixedcontent/#restricts-mixed-content ( for easy overriding in tests )
|
* Shortcut method for https://w3c.github.io/webappsec/specs/mixedcontent/#restricts-mixed-content ( for easy overriding in tests )
|
||||||
@ -94,13 +122,12 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
/**
|
/**
|
||||||
* Shortcut method for matchMedia ( for easy overriding in tests )
|
* Shortcut method for matchMedia ( for easy overriding in tests )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pf.matchesMedia = function( media ) {
|
pf.matchesMedia = function( media ) {
|
||||||
return w.matchMedia && w.matchMedia( media ).matches;
|
return w.matchMedia && w.matchMedia( media ).matches;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// Shortcut method for `devicePixelRatio` ( for easy overriding in tests )
|
||||||
* Shortcut method for `devicePixelRatio` ( for easy overriding in tests )
|
|
||||||
*/
|
|
||||||
pf.getDpr = function() {
|
pf.getDpr = function() {
|
||||||
return ( w.devicePixelRatio || 1 );
|
return ( w.devicePixelRatio || 1 );
|
||||||
};
|
};
|
||||||
@ -110,87 +137,99 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
* http://dev.w3.org/csswg/css-values-3/#length-value
|
* http://dev.w3.org/csswg/css-values-3/#length-value
|
||||||
*/
|
*/
|
||||||
pf.getWidthFromLength = function( length ) {
|
pf.getWidthFromLength = function( length ) {
|
||||||
// If a length is specified and doesn’t contain a percentage, and it is greater than 0 or using `calc`, use it. Else, use the `100vw` default.
|
var cssValue;
|
||||||
length = length && length.indexOf( "%" ) > -1 === false && ( parseFloat( length ) > 0 || length.indexOf( "calc(" ) > -1 ) ? length : "100vw";
|
// If a length is specified and doesn’t contain a percentage, and it is greater than 0 or using `calc`, use it. Else, abort.
|
||||||
|
if ( !(length && length.indexOf( "%" ) > -1 === false && ( parseFloat( length ) > 0 || length.indexOf( "calc(" ) > -1 )) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If length is specified in `vw` units, use `%` instead since the div we’re measuring
|
* If length is specified in `vw` units, use `%` instead since the div we’re measuring
|
||||||
* is injected at the top of the document.
|
* is injected at the top of the document.
|
||||||
*
|
*
|
||||||
* TODO: maybe we should put this behind a feature test for `vw`?
|
* TODO: maybe we should put this behind a feature test for `vw`? The risk of doing this is possible browser inconsistancies with vw vs %
|
||||||
*/
|
*/
|
||||||
length = length.replace( "vw", "%" );
|
length = length.replace( "vw", "%" );
|
||||||
|
|
||||||
// Create a cached element for getting length value widths
|
// Create a cached element for getting length value widths
|
||||||
if ( !pf.lengthEl ) {
|
if ( !pf.lengthEl ) {
|
||||||
pf.lengthEl = doc.createElement( "div" );
|
pf.lengthEl = doc.createElement( "div" );
|
||||||
doc.documentElement.insertBefore( pf.lengthEl, doc.documentElement.firstChild );
|
|
||||||
|
// Positioning styles help prevent padding/margin/width on `html` or `body` from throwing calculations off.
|
||||||
|
pf.lengthEl.style.cssText = "border:0;display:block;font-size:1em;left:0;margin:0;padding:0;position:absolute;visibility:hidden";
|
||||||
|
|
||||||
|
// Add a class, so that everyone knows where this element comes from
|
||||||
|
pf.lengthEl.className = "helper-from-picturefill-js";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Positioning styles help prevent padding/margin/width on `html` from throwing calculations off.
|
pf.lengthEl.style.width = "0px";
|
||||||
pf.lengthEl.style.cssText = "position: absolute; left: 0; width: " + length + ";";
|
|
||||||
|
|
||||||
if ( pf.lengthEl.offsetWidth <= 0 ) {
|
try {
|
||||||
// Something has gone wrong. `calc()` is in use and unsupported, most likely. Default to `100vw` (`100%`, for broader support.):
|
pf.lengthEl.style.width = length;
|
||||||
pf.lengthEl.style.cssText = "width: 100%;";
|
} catch ( e ) {}
|
||||||
|
|
||||||
|
doc.body.appendChild(pf.lengthEl);
|
||||||
|
|
||||||
|
cssValue = pf.lengthEl.offsetWidth;
|
||||||
|
|
||||||
|
if ( cssValue <= 0 ) {
|
||||||
|
cssValue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pf.lengthEl.offsetWidth;
|
doc.body.removeChild( pf.lengthEl );
|
||||||
|
|
||||||
|
return cssValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pf.detectTypeSupport = function( type, typeUri ) {
|
||||||
|
// based on Modernizr's lossless img-webp test
|
||||||
|
// note: asynchronous
|
||||||
|
var image = new w.Image();
|
||||||
|
image.onerror = function() {
|
||||||
|
pf.types[ type ] = false;
|
||||||
|
picturefill();
|
||||||
|
};
|
||||||
|
image.onload = function() {
|
||||||
|
pf.types[ type ] = image.width === 1;
|
||||||
|
picturefill();
|
||||||
|
};
|
||||||
|
image.src = typeUri;
|
||||||
|
|
||||||
|
return "pending";
|
||||||
|
};
|
||||||
// container of supported mime types that one might need to qualify before using
|
// container of supported mime types that one might need to qualify before using
|
||||||
pf.types = {};
|
pf.types = pf.types || {};
|
||||||
|
|
||||||
// Add support for standard mime types.
|
pf.initTypeDetects = function() {
|
||||||
pf.types["image/jpeg"] = true;
|
// Add support for standard mime types
|
||||||
pf.types["image/gif"] = true;
|
pf.types[ "image/jpeg" ] = true;
|
||||||
pf.types["image/png"] = true;
|
pf.types[ "image/gif" ] = true;
|
||||||
|
pf.types[ "image/png" ] = true;
|
||||||
|
pf.types[ "image/svg+xml" ] = doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1");
|
||||||
|
pf.types[ "image/webp" ] = pf.detectTypeSupport("image/webp", "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=");
|
||||||
|
};
|
||||||
|
|
||||||
// test svg support
|
|
||||||
pf.types[ "image/svg+xml" ] = doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1");
|
|
||||||
|
|
||||||
// test webp support, only when the markup calls for it
|
|
||||||
pf.types[ "image/webp" ] = function() {
|
|
||||||
// based on Modernizr's lossless img-webp test
|
|
||||||
// note: asynchronous
|
|
||||||
var img = new w.Image(),
|
|
||||||
type = "image/webp";
|
|
||||||
|
|
||||||
img.onerror = function() {
|
|
||||||
pf.types[ type ] = false;
|
|
||||||
picturefill();
|
|
||||||
};
|
|
||||||
img.onload = function() {
|
|
||||||
pf.types[ type ] = img.width === 1;
|
|
||||||
picturefill();
|
|
||||||
};
|
|
||||||
img.src = "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=";
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a source element and checks if its type attribute is present and if so, supported
|
|
||||||
* Note: for type tests that require a async logic,
|
|
||||||
* you can define them as a function that'll run only if that type needs to be tested. Just make the test function call picturefill again when it is complete.
|
|
||||||
* see the async webp test above for example
|
|
||||||
*/
|
|
||||||
pf.verifyTypeSupport = function( source ) {
|
pf.verifyTypeSupport = function( source ) {
|
||||||
var type = source.getAttribute( "type" );
|
var type = source.getAttribute( "type" );
|
||||||
// if type attribute exists, return test result, otherwise return true
|
// if type attribute exists, return test result, otherwise return true
|
||||||
if ( type === null || type === "" ) {
|
if ( type === null || type === "" ) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
var pfType = pf.types[ type ];
|
||||||
// if the type test is a function, run it and return "pending" status. The function will rerun picturefill on pending elements once finished.
|
// if the type test is a function, run it and return "pending" status. The function will rerun picturefill on pending elements once finished.
|
||||||
if ( typeof( pf.types[ type ] ) === "function" ) {
|
if ( typeof pfType === "string" && pfType !== "pending") {
|
||||||
pf.types[ type ]();
|
pf.types[ type ] = pf.detectTypeSupport( type, pfType );
|
||||||
|
return "pending";
|
||||||
|
} else if ( typeof pfType === "function" ) {
|
||||||
|
pfType();
|
||||||
return "pending";
|
return "pending";
|
||||||
} else {
|
} else {
|
||||||
return pf.types[ type ];
|
return pfType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// Parses an individual `size` and returns the length, and optional media query
|
||||||
* Parses an individual `size` and returns the length, and optional media query
|
|
||||||
*/
|
|
||||||
pf.parseSize = function( sourceSizeStr ) {
|
pf.parseSize = function( sourceSizeStr ) {
|
||||||
var match = /(\([^)]+\))?\s*(.+)/g.exec( sourceSizeStr );
|
var match = /(\([^)]+\))?\s*(.+)/g.exec( sourceSizeStr );
|
||||||
return {
|
return {
|
||||||
@ -199,9 +238,7 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// Takes a string of sizes and returns the width in pixels as a number
|
||||||
* Takes a string of sizes and returns the width in pixels as a number
|
|
||||||
*/
|
|
||||||
pf.findWidthFromSourceSize = function( sourceSizeListStr ) {
|
pf.findWidthFromSourceSize = function( sourceSizeListStr ) {
|
||||||
// Split up source size list, ie ( max-width: 30em ) 100%, ( max-width: 50em ) 50%, 33%
|
// Split up source size list, ie ( max-width: 30em ) 100%, ( max-width: 50em ) 50%, 33%
|
||||||
// or (min-width:30em) calc(30% - 15px)
|
// or (min-width:30em) calc(30% - 15px)
|
||||||
@ -219,34 +256,34 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
if ( !length ) {
|
if ( !length ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( !media || pf.matchesMedia( media ) ) {
|
// if there is no media query or it matches, choose this as our winning length
|
||||||
// if there is no media query or it matches, choose this as our winning length
|
if ( (!media || pf.matchesMedia( media )) &&
|
||||||
// and end algorithm
|
// pass the length to a method that can properly determine length
|
||||||
winningLength = length;
|
// in pixels based on these formats: http://dev.w3.org/csswg/css-values-3/#length-value
|
||||||
|
(winningLength = pf.getWidthFromLength( length )) ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass the length to a method that can properly determine length
|
//if we have no winningLength fallback to 100vw
|
||||||
// in pixels based on these formats: http://dev.w3.org/csswg/css-values-3/#length-value
|
return winningLength || Math.max(w.innerWidth || 0, doc.documentElement.clientWidth);
|
||||||
return pf.getWidthFromLength( winningLength );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pf.parseSrcset = function( srcset ) {
|
pf.parseSrcset = function( srcset ) {
|
||||||
/**
|
/**
|
||||||
* A lot of this was pulled from Boris Smus’ parser for the now-defunct WHATWG `srcset`
|
* A lot of this was pulled from Boris Smus’ parser for the now-defunct WHATWG `srcset`
|
||||||
* https://github.com/borismus/srcset-polyfill/blob/master/js/srcset-info.js
|
* https://github.com/borismus/srcset-polyfill/blob/master/js/srcset-info.js
|
||||||
*
|
*
|
||||||
* 1. Let input (`srcset`) be the value passed to this algorithm.
|
* 1. Let input (`srcset`) be the value passed to this algorithm.
|
||||||
* 2. Let position be a pointer into input, initially pointing at the start of the string.
|
* 2. Let position be a pointer into input, initially pointing at the start of the string.
|
||||||
* 3. Let raw candidates be an initially empty ordered list of URLs with associated
|
* 3. Let raw candidates be an initially empty ordered list of URLs with associated
|
||||||
* unparsed descriptors. The order of entries in the list is the order in which entries
|
* unparsed descriptors. The order of entries in the list is the order in which entries
|
||||||
* are added to the list.
|
* are added to the list.
|
||||||
*/
|
*/
|
||||||
var candidates = [];
|
var candidates = [];
|
||||||
|
|
||||||
while ( srcset !== "" ) {
|
while ( srcset !== "" ) {
|
||||||
srcset = srcset.replace(/^\s+/g,"");
|
srcset = srcset.replace( /^\s+/g, "" );
|
||||||
|
|
||||||
// 5. Collect a sequence of characters that are not space characters, and let that be url.
|
// 5. Collect a sequence of characters that are not space characters, and let that be url.
|
||||||
var pos = srcset.search(/\s/g),
|
var pos = srcset.search(/\s/g),
|
||||||
@ -255,14 +292,14 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
if ( pos !== -1 ) {
|
if ( pos !== -1 ) {
|
||||||
url = srcset.slice( 0, pos );
|
url = srcset.slice( 0, pos );
|
||||||
|
|
||||||
var last = url[ url.length - 1 ];
|
var last = url.slice(-1);
|
||||||
|
|
||||||
// 6. If url ends with a U+002C COMMA character (,), remove that character from url
|
// 6. If url ends with a U+002C COMMA character (,), remove that character from url
|
||||||
// and let descriptors be the empty string. Otherwise, follow these substeps
|
// and let descriptors be the empty string. Otherwise, follow these substeps
|
||||||
// 6.1. If url is empty, then jump to the step labeled descriptor parser.
|
// 6.1. If url is empty, then jump to the step labeled descriptor parser.
|
||||||
|
|
||||||
if ( last === "," || url === "" ) {
|
if ( last === "," || url === "" ) {
|
||||||
url = url.replace(/,+$/, "");
|
url = url.replace( /,+$/, "" );
|
||||||
descriptor = "";
|
descriptor = "";
|
||||||
}
|
}
|
||||||
srcset = srcset.slice( pos + 1 );
|
srcset = srcset.slice( pos + 1 );
|
||||||
@ -270,7 +307,7 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
// 6.2. Collect a sequence of characters that are not U+002C COMMA characters (,), and
|
// 6.2. Collect a sequence of characters that are not U+002C COMMA characters (,), and
|
||||||
// let that be descriptors.
|
// let that be descriptors.
|
||||||
if ( descriptor === null ) {
|
if ( descriptor === null ) {
|
||||||
var descpos = srcset.indexOf(",");
|
var descpos = srcset.indexOf( "," );
|
||||||
if ( descpos !== -1 ) {
|
if ( descpos !== -1 ) {
|
||||||
descriptor = srcset.slice( 0, descpos );
|
descriptor = srcset.slice( 0, descpos );
|
||||||
srcset = srcset.slice( descpos + 1 );
|
srcset = srcset.slice( descpos + 1 );
|
||||||
@ -299,24 +336,22 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
// 11. Descriptor parser: Let candidates be an initially empty source set. The order of entries in the list
|
// 11. Descriptor parser: Let candidates be an initially empty source set. The order of entries in the list
|
||||||
// is the order in which entries are added to the list.
|
// is the order in which entries are added to the list.
|
||||||
var sizes = sizesattr || "100vw",
|
var sizes = sizesattr || "100vw",
|
||||||
sizeDescriptor = descriptor && descriptor.replace(/(^\s+|\s+$)/g, ""),
|
sizeDescriptor = descriptor && descriptor.replace( /(^\s+|\s+$)/g, "" ),
|
||||||
widthInCssPixels = pf.findWidthFromSourceSize( sizes ),
|
widthInCssPixels = pf.findWidthFromSourceSize( sizes ),
|
||||||
resCandidate;
|
resCandidate;
|
||||||
|
|
||||||
if ( sizeDescriptor ) {
|
if ( sizeDescriptor ) {
|
||||||
var splitDescriptor = sizeDescriptor.split(" ");
|
var splitDescriptor = sizeDescriptor.split(" ");
|
||||||
|
|
||||||
for (var i = splitDescriptor.length + 1; i >= 0; i--) {
|
for (var i = splitDescriptor.length - 1; i >= 0; i--) {
|
||||||
if ( splitDescriptor[ i ] !== undefined ) {
|
var curr = splitDescriptor[ i ],
|
||||||
var curr = splitDescriptor[ i ],
|
lastchar = curr && curr.slice( curr.length - 1 );
|
||||||
lastchar = curr && curr.slice( curr.length - 1 );
|
|
||||||
|
|
||||||
if ( ( lastchar === "h" || lastchar === "w" ) && !pf.sizesSupported ) {
|
if ( ( lastchar === "h" || lastchar === "w" ) && !pf.sizesSupported ) {
|
||||||
resCandidate = parseFloat( ( parseInt( curr, 10 ) / widthInCssPixels ) );
|
resCandidate = parseFloat( ( parseInt( curr, 10 ) / widthInCssPixels ) );
|
||||||
} else if ( lastchar === "x" ) {
|
} else if ( lastchar === "x" ) {
|
||||||
var res = curr && parseFloat( curr, 10 );
|
var res = curr && parseFloat( curr, 10 );
|
||||||
resCandidate = res && !isNaN( res ) ? res : 1;
|
resCandidate = res && !isNaN( res ) ? res : 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,7 +383,7 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
return formattedCandidates;
|
return formattedCandidates;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* if it's an img element and it has a srcset property,
|
* if it's an img element and it has a srcset property,
|
||||||
* we need to remove the attribute so we can manipulate src
|
* we need to remove the attribute so we can manipulate src
|
||||||
* (the property's existence infers native srcset support, and a srcset-supporting browser will prioritize srcset's value over our winning picture candidate)
|
* (the property's existence infers native srcset support, and a srcset-supporting browser will prioritize srcset's value over our winning picture candidate)
|
||||||
@ -357,13 +392,12 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
pf.dodgeSrcset = function( img ) {
|
pf.dodgeSrcset = function( img ) {
|
||||||
if ( img.srcset ) {
|
if ( img.srcset ) {
|
||||||
img[ pf.ns ].srcset = img.srcset;
|
img[ pf.ns ].srcset = img.srcset;
|
||||||
img.removeAttribute( "srcset" );
|
img.srcset = "";
|
||||||
|
img.setAttribute( "data-pfsrcset", img[ pf.ns ].srcset );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
// Accept a source or img element and process its srcset and sizes attrs
|
||||||
* Accept a source or img element and process its srcset and sizes attrs
|
|
||||||
*/
|
|
||||||
pf.processSourceSet = function( el ) {
|
pf.processSourceSet = function( el ) {
|
||||||
var srcset = el.getAttribute( "srcset" ),
|
var srcset = el.getAttribute( "srcset" ),
|
||||||
sizes = el.getAttribute( "sizes" ),
|
sizes = el.getAttribute( "sizes" ),
|
||||||
@ -380,6 +414,66 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
return candidates;
|
return candidates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pf.backfaceVisibilityFix = function( picImg ) {
|
||||||
|
// See: https://github.com/scottjehl/picturefill/issues/332
|
||||||
|
var style = picImg.style || {},
|
||||||
|
WebkitBackfaceVisibility = "webkitBackfaceVisibility" in style,
|
||||||
|
currentZoom = style.zoom;
|
||||||
|
|
||||||
|
if (WebkitBackfaceVisibility) {
|
||||||
|
style.zoom = ".999";
|
||||||
|
|
||||||
|
WebkitBackfaceVisibility = picImg.offsetWidth;
|
||||||
|
|
||||||
|
style.zoom = currentZoom;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pf.setIntrinsicSize = (function() {
|
||||||
|
var urlCache = {};
|
||||||
|
var setSize = function( picImg, width, res ) {
|
||||||
|
if ( width ) {
|
||||||
|
picImg.setAttribute( "width", parseInt(width / res, 10) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return function( picImg, bestCandidate ) {
|
||||||
|
var img;
|
||||||
|
if ( !picImg[ pf.ns ] || w.pfStopIntrinsicSize ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( picImg[ pf.ns ].dims === undefined ) {
|
||||||
|
picImg[ pf.ns].dims = picImg.getAttribute("width") || picImg.getAttribute("height");
|
||||||
|
}
|
||||||
|
if ( picImg[ pf.ns].dims ) { return; }
|
||||||
|
|
||||||
|
if ( bestCandidate.url in urlCache ) {
|
||||||
|
setSize( picImg, urlCache[bestCandidate.url], bestCandidate.resolution );
|
||||||
|
} else {
|
||||||
|
img = doc.createElement( "img" );
|
||||||
|
img.onload = function() {
|
||||||
|
urlCache[bestCandidate.url] = img.width;
|
||||||
|
|
||||||
|
//IE 10/11 don't calculate width for svg outside document
|
||||||
|
if ( !urlCache[bestCandidate.url] ) {
|
||||||
|
try {
|
||||||
|
doc.body.appendChild( img );
|
||||||
|
urlCache[bestCandidate.url] = img.width || img.offsetWidth;
|
||||||
|
doc.body.removeChild( img );
|
||||||
|
} catch(e){}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( picImg.src === bestCandidate.url ) {
|
||||||
|
setSize( picImg, urlCache[bestCandidate.url], bestCandidate.resolution );
|
||||||
|
}
|
||||||
|
picImg = null;
|
||||||
|
img.onload = null;
|
||||||
|
img = null;
|
||||||
|
};
|
||||||
|
img.src = bestCandidate.url;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
pf.applyBestCandidate = function( candidates, picImg ) {
|
pf.applyBestCandidate = function( candidates, picImg ) {
|
||||||
var candidate,
|
var candidate,
|
||||||
length,
|
length,
|
||||||
@ -398,17 +492,28 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bestCandidate && !pf.endsWith( picImg.src, bestCandidate.url ) ) {
|
if ( bestCandidate ) {
|
||||||
if ( pf.restrictsMixedContent() && bestCandidate.url.substr(0, "http:".length).toLowerCase() === "http:" ) {
|
|
||||||
if ( typeof console !== undefined ) {
|
bestCandidate.url = pf.makeUrl( bestCandidate.url );
|
||||||
console.warn( "Blocked mixed content image " + bestCandidate.url );
|
|
||||||
|
if ( picImg.src !== bestCandidate.url ) {
|
||||||
|
if ( pf.restrictsMixedContent() && bestCandidate.url.substr(0, "http:".length).toLowerCase() === "http:" ) {
|
||||||
|
if ( window.console !== undefined ) {
|
||||||
|
console.warn( "Blocked mixed content image " + bestCandidate.url );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
picImg.src = bestCandidate.url;
|
||||||
|
// currentSrc attribute and property to match
|
||||||
|
// http://picture.responsiveimages.org/#the-img-element
|
||||||
|
if ( !pf.curSrcSupported ) {
|
||||||
|
picImg.currentSrc = picImg.src;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf.backfaceVisibilityFix( picImg );
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
picImg.src = bestCandidate.url;
|
|
||||||
// currentSrc attribute and property to match
|
|
||||||
// http://picture.responsiveimages.org/#the-img-element
|
|
||||||
picImg.currentSrc = picImg.src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pf.setIntrinsicSize(picImg, bestCandidate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -416,7 +521,7 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
return a.resolution - b.resolution;
|
return a.resolution - b.resolution;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* In IE9, <source> elements get removed if they aren't children of
|
* In IE9, <source> elements get removed if they aren't children of
|
||||||
* video elements. Thus, we conditionally wrap source elements
|
* video elements. Thus, we conditionally wrap source elements
|
||||||
* using <!--[if IE 9]><video style="display: none;"><![endif]-->
|
* using <!--[if IE 9]><video style="display: none;"><![endif]-->
|
||||||
@ -436,7 +541,7 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Find all `img` elements, and add them to the candidate list if they have
|
* Find all `img` elements, and add them to the candidate list if they have
|
||||||
* a `picture` parent, a `sizes` attribute in basic `srcset` supporting browsers,
|
* a `picture` parent, a `sizes` attribute in basic `srcset` supporting browsers,
|
||||||
* a `srcset` attribute at all, and they haven’t been evaluated already.
|
* a `srcset` attribute at all, and they haven’t been evaluated already.
|
||||||
@ -449,8 +554,8 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
var currImg = imgs[ h ];
|
var currImg = imgs[ h ];
|
||||||
|
|
||||||
if ( currImg.parentNode.nodeName.toUpperCase() === "PICTURE" ||
|
if ( currImg.parentNode.nodeName.toUpperCase() === "PICTURE" ||
|
||||||
( currImg.getAttribute( "srcset" ) !== null ) || currImg[ pf.ns ] && currImg[ pf.ns ].srcset !== null ) {
|
( currImg.getAttribute( "srcset" ) !== null ) || currImg[ pf.ns ] && currImg[ pf.ns ].srcset !== null ) {
|
||||||
elems.push( currImg );
|
elems.push( currImg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return elems;
|
return elems;
|
||||||
@ -480,7 +585,7 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// if it's a source element that has the `src` property set, throw a warning in the console
|
// if it's a source element that has the `src` property set, throw a warning in the console
|
||||||
if ( source.getAttribute( "src" ) !== null && typeof console !== undefined ){
|
if ( source.getAttribute( "src" ) !== null && typeof console !== undefined ) {
|
||||||
console.warn("The `src` attribute is invalid on `picture` `source` element; instead, use `srcset`.");
|
console.warn("The `src` attribute is invalid on `picture` `source` element; instead, use `srcset`.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,8 +618,8 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
parent,
|
parent,
|
||||||
firstMatch,
|
firstMatch,
|
||||||
candidates,
|
candidates,
|
||||||
|
options = opt || {};
|
||||||
|
|
||||||
options = opt || {};
|
|
||||||
elements = options.elements || pf.getAllElements();
|
elements = options.elements || pf.getAllElements();
|
||||||
|
|
||||||
// Loop through all elements
|
// Loop through all elements
|
||||||
@ -524,20 +629,25 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
firstMatch = undefined;
|
firstMatch = undefined;
|
||||||
candidates = undefined;
|
candidates = undefined;
|
||||||
|
|
||||||
|
// immediately skip non-`img` nodes
|
||||||
|
if ( element.nodeName.toUpperCase() !== "IMG" ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// expando for caching data on the img
|
// expando for caching data on the img
|
||||||
if ( !element[ pf.ns ] ) {
|
if ( !element[ pf.ns ] ) {
|
||||||
element[ pf.ns ] = {};
|
element[ pf.ns ] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the element has already been evaluated, skip it
|
// if the element has already been evaluated, skip it unless
|
||||||
// unless `options.force` is set to true ( this, for example,
|
// `options.reevaluate` is set to true ( this, for example,
|
||||||
// is set to true when running `picturefill` on `resize` ).
|
// is set to true when running `picturefill` on `resize` ).
|
||||||
if ( !options.reevaluate && element[ pf.ns ].evaluated ) {
|
if ( !options.reevaluate && element[ pf.ns ].evaluated ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if `img` is in a `picture` element
|
// if `img` is in a `picture` element
|
||||||
if ( parent.nodeName.toUpperCase() === "PICTURE" ) {
|
if ( parent && parent.nodeName.toUpperCase() === "PICTURE" ) {
|
||||||
|
|
||||||
// IE9 video workaround
|
// IE9 video workaround
|
||||||
pf.removeVideoShim( parent );
|
pf.removeVideoShim( parent );
|
||||||
@ -558,9 +668,8 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache and remove `srcset` if present and we’re going to be doing `picture`/`srcset`/`sizes` polyfilling to it.
|
// Cache and remove `srcset` if present and we’re going to be doing `picture`/`srcset`/`sizes` polyfilling to it.
|
||||||
if ( parent.nodeName.toUpperCase() === "PICTURE" ||
|
if ( ( parent && parent.nodeName.toUpperCase() === "PICTURE" ) ||
|
||||||
( element.srcset && !pf.srcsetSupported ) ||
|
( !pf.sizesSupported && ( element.srcset && regWDesc.test( element.srcset ) ) ) ) {
|
||||||
( !pf.sizesSupported && ( element.srcset && element.srcset.indexOf("w") > -1 ) ) ) {
|
|
||||||
pf.dodgeSrcset( element );
|
pf.dodgeSrcset( element );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,28 +697,32 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
* Also attaches picturefill on resize
|
* Also attaches picturefill on resize
|
||||||
*/
|
*/
|
||||||
function runPicturefill() {
|
function runPicturefill() {
|
||||||
|
pf.initTypeDetects();
|
||||||
picturefill();
|
picturefill();
|
||||||
var intervalId = setInterval( function() {
|
var intervalId = setInterval( function() {
|
||||||
// When the document has finished loading, stop checking for new images
|
// When the document has finished loading, stop checking for new images
|
||||||
// https://github.com/ded/domready/blob/master/ready.js#L15
|
// https://github.com/ded/domready/blob/master/ready.js#L15
|
||||||
picturefill();
|
picturefill();
|
||||||
|
|
||||||
if ( /^loaded|^i|^c/.test( doc.readyState ) ) {
|
if ( /^loaded|^i|^c/.test( doc.readyState ) ) {
|
||||||
clearInterval( intervalId );
|
clearInterval( intervalId );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, 250 );
|
}, 250 );
|
||||||
|
|
||||||
|
var resizeTimer;
|
||||||
|
var handleResize = function() {
|
||||||
|
picturefill({ reevaluate: true });
|
||||||
|
};
|
||||||
|
function checkResize() {
|
||||||
|
clearTimeout(resizeTimer);
|
||||||
|
resizeTimer = setTimeout( handleResize, 60 );
|
||||||
|
}
|
||||||
|
|
||||||
if ( w.addEventListener ) {
|
if ( w.addEventListener ) {
|
||||||
var resizeThrottle;
|
w.addEventListener( "resize", checkResize, false );
|
||||||
w.addEventListener( "resize", function() {
|
} else if ( w.attachEvent ) {
|
||||||
if (!w._picturefillWorking) {
|
w.attachEvent( "onresize", checkResize );
|
||||||
w._picturefillWorking = true;
|
|
||||||
w.clearTimeout( resizeThrottle );
|
|
||||||
resizeThrottle = w.setTimeout( function() {
|
|
||||||
picturefill({ reevaluate: true });
|
|
||||||
w._picturefillWorking = false;
|
|
||||||
}, 60 );
|
|
||||||
}
|
|
||||||
}, false );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,16 +731,6 @@ window.matchMedia || (window.matchMedia = function() {
|
|||||||
/* expose methods for testing */
|
/* expose methods for testing */
|
||||||
picturefill._ = pf;
|
picturefill._ = pf;
|
||||||
|
|
||||||
/* expose picturefill */
|
expose( picturefill );
|
||||||
if ( typeof module === "object" && typeof module.exports === "object" ) {
|
|
||||||
// CommonJS, just export
|
|
||||||
module.exports = picturefill;
|
|
||||||
} else if ( typeof define === "function" && define.amd ){
|
|
||||||
// AMD support
|
|
||||||
define( function() { return picturefill; } );
|
|
||||||
} else if ( typeof w === "object" ) {
|
|
||||||
// If no AMD and we are in the browser, attach to window
|
|
||||||
w.picturefill = picturefill;
|
|
||||||
}
|
|
||||||
|
|
||||||
} )( this, this.document );
|
} )( window, window.document, new window.Image() );
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user