From 7ad28a04f5bcafef155d2156e248eed81cf8210d Mon Sep 17 00:00:00 2001 From: Andrea Verlicchi Date: Fri, 25 Jul 2014 09:47:23 +0200 Subject: [PATCH] Fixed a bug occurring when no source media matched Releasing v4.1.3 and fixing a bug that occurred then no source media matched --- Gruntfile.js | 2 +- bower.json | 2 +- dist/picturePolyfill.min.js | 4 +- src/picturePolyfill.js | 23 ++++----- test/picturePolyfill.qunit.js | 95 ++++++++++++++++++++++++++++------- 5 files changed, 89 insertions(+), 37 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index eedd37d..97827b7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -5,7 +5,7 @@ module.exports = function(grunt) { grunt.initConfig({ // Metadata. meta: { - version: '4.1.2' + version: '4.1.3' }, banner: '/*! picturePolyfill - v<%= meta.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + diff --git a/bower.json b/bower.json index e5057b1..4faf2b2 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "picturePolyfill", - "version": "4.1.2", + "version": "4.1.3", "main": "picturePolyfill.js", "ignore": [ ".idea", diff --git a/dist/picturePolyfill.min.js b/dist/picturePolyfill.min.js index 65d0218..84adfcc 100644 --- a/dist/picturePolyfill.min.js +++ b/dist/picturePolyfill.min.js @@ -1,4 +1,4 @@ -/*! picturePolyfill - v4.1.2 - 2014-07-24 +/*! picturePolyfill - v4.1.3 - 2014-07-25 * https://github.com/verlok/picturePolyfill/ * Copyright (c) 2014 Andrea "verlok" Verlicchi; Licensed MIT */ -var picturePolyfill=function(a){"use strict";var b,c,d,e=100,f=!1;return{_getAttrs:function(a,b){for(var c,d,e={},f=0,g=b.length;g>f;f+=1)c=b[f],d=a.getAttribute(c),d&&(e[c]=d);return e},_getAttrsList:function(a){for(var b=[],c=0,d=a.attributes,e=d.length;e>c;c++)b.push(d.item(c).nodeName);return b},_getSrcsetArray:function(a){var b,c,d,e,f=[];if(null===a||""===a||"undefined"==typeof a)return f;e=a.split(",");for(var g=0,h=e.length;h>g;g+=1)b=e[g].trim().split(" "),d=1===b.length?1:parseFloat(b[b.length-1],10),c=b[0],f.push({pxr:d,src:c});return f.sort(function(a,b){var c=a.pxr,d=b.pxr;return d>c?-1:c>d?1:0})},_getSrcFromSrcset:function(a,b){var c,d,e=0,f=-1;if(null===a||""===a||"undefined"==typeof a)return null;c=this._getSrcsetArray(a),d=c.length;do(c[e].pxr>=b||e===d-1)&&(f=e),e+=1;while(!(f>-1||e>=d));return c[f].src},_getSrcsetFromData:function(b){for(var c,d,e,f,g=0,h=b.length;h>g;g+=1)if(c=b[g],d=c.media,f=c.srcset,e=c.src,!d||a.matchMedia(d).matches)return f?f:e?e:"";return""},_setImgAttributes:function(a,b){function c(a,b,c){a.getAttribute(b)!==c&&a.setAttribute(b,c)}var d,e,f,g,h,i,j,k=a.getElementsByTagName("img");return 0===k.length?!1:(d=k[0],e=d.getAttribute("data-original-src"),f=d.getAttribute("data-original-srcset"),g=b.src,h=b.srcset,e||(c(d,"data-original-src",d.getAttribute("src")),c(d,"data-original-srcset",d.getAttribute("srcset"))),g||h?(i=g,j=h):(i=e,j=f),c(d,"src",i),void c(d,"srcset",j))},_getSourcesData:function(a){for(var b,c,d=[],e=a.getElementsByTagName("source"),f=0,g=e.length;g>f;f+=1)b=e[f],c=this._getAttrs(b,this._getAttrsList(b)),d.push(c);return d},_addListeners:function(){function b(){picturePolyfill.parse(document)}function c(){clearTimeout(d),d=setTimeout(b,e)}return!this.isUseful||f?!1:(a.addEventListener?(a.addEventListener("resize",c),a.addEventListener("DOMContentLoaded",function(){b(),a.removeEventListener("load",b)}),a.addEventListener("load",b)):a.attachEvent&&(a.attachEvent("onload",b),a.attachEvent("onresize",c)),void(f=!0))},initialize:function(){this._pxRatio=a.devicePixelRatio||1,this._mqSupport=!!a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,this.isUseful=!a.HTMLPictureElement,b=[],c=0,this._addListeners()},parse:function(a,d){var e,f,g,h,i,j,k;if(!this.isUseful)return 0;"undefined"==typeof d&&(d=!0),g=(a||document).getElementsByTagName("picture"),j=this._mqSupport;for(var l=0,m=g.length;m>l;l+=1)e=null,f=g[l],d&&(k=f.getAttribute("data-cache-index"),null!==k&&(e=b[k])),e||(e=this._getSourcesData(f),b[c]=e,f.setAttribute("data-cache-index",c),c+=1),j&&0!==e.length?(i=this._getSrcsetFromData(e),h=this._getSrcFromSrcset(i,this._pxRatio)):(h=f.getAttribute("data-default-src"),i=f.getAttribute("data-default-srcset")),this._setImgAttributes(f,{src:h,srcset:i,alt:f.getAttribute("data-alt")});return l}}}(window);picturePolyfill.initialize(),picturePolyfill.parse(); \ No newline at end of file +var picturePolyfill=function(a){"use strict";var b,c,d,e=100,f=!1;return{_getAttrs:function(a,b){for(var c,d,e={},f=0,g=b.length;g>f;f+=1)c=b[f],d=a.getAttribute(c),d&&(e[c]=d);return e},_getAttrsList:function(a){for(var b=[],c=0,d=a.attributes,e=d.length;e>c;c++)b.push(d.item(c).nodeName);return b},_getSrcsetArray:function(a){var b,c,d,e,f=[];if(null===a||""===a||"undefined"==typeof a)return f;e=a.split(",");for(var g=0,h=e.length;h>g;g+=1)b=e[g].trim().split(" "),d=1===b.length?1:parseFloat(b[b.length-1],10),c=b[0],f.push({pxr:d,src:c});return f.sort(function(a,b){var c=a.pxr,d=b.pxr;return d>c?-1:c>d?1:0})},_getSrcFromSrcset:function(a,b){var c,d,e=0,f=-1;if(null===a||""===a||"undefined"==typeof a)return"";c=this._getSrcsetArray(a),d=c.length;do(c[e].pxr>=b||e===d-1)&&(f=e),e+=1;while(!(f>-1||e>=d));return c[f].src},_getSrcsetFromData:function(b){for(var c,d,e,f,g=0,h=b.length;h>g;g+=1)if(c=b[g],d=c.media,f=c.srcset,e=c.src,!d||a.matchMedia(d).matches)return f?f:e?e:"";return""},_setImgAttributes:function(a,b){function c(a,b,c){a.getAttribute(b)!==c&&a.setAttribute(b,c)}var d,e,f,g,h,i=a.getElementsByTagName("img");return 0===i.length?!1:(d=i[0],d.getAttribute("data-original-src")||(c(d,"data-original-src",d.getAttribute("src")),c(d,"data-original-srcset",d.getAttribute("srcset"))),e=b.src,f=b.srcset,e||f?(g=e,h=f):(g=d.getAttribute("data-original-src"),h=d.getAttribute("data-original-srcset")),c(d,"src",g),void c(d,"srcset",h))},_getSourcesData:function(a){for(var b,c,d=[],e=a.getElementsByTagName("source"),f=0,g=e.length;g>f;f+=1)b=e[f],c=this._getAttrs(b,this._getAttrsList(b)),d.push(c);return d},_addListeners:function(){function b(){picturePolyfill.parse(document)}function c(){clearTimeout(d),d=setTimeout(b,e)}return!this.isUseful||f?!1:(a.addEventListener?(a.addEventListener("resize",c),a.addEventListener("DOMContentLoaded",function(){b(),a.removeEventListener("load",b)}),a.addEventListener("load",b)):a.attachEvent&&(a.attachEvent("onload",b),a.attachEvent("onresize",c)),void(f=!0))},initialize:function(){this._pxRatio=a.devicePixelRatio||1,this._mqSupport=!!a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,this.isUseful=!a.HTMLPictureElement,b=[],c=0,this._addListeners()},parse:function(a,d){var e,f,g,h,i,j,k;if(!this.isUseful)return 0;"undefined"==typeof d&&(d=!0),g=(a||document).getElementsByTagName("picture"),j=this._mqSupport;for(var l=0,m=g.length;m>l;l+=1)e=null,f=g[l],d&&(k=f.getAttribute("data-cache-index"),null!==k&&(e=b[k])),e||(e=this._getSourcesData(f),b[c]=e,f.setAttribute("data-cache-index",c),c+=1),j&&0!==e.length?(i=this._getSrcsetFromData(e),h=this._getSrcFromSrcset(i,this._pxRatio)):(h=f.getAttribute("data-default-src"),i=f.getAttribute("data-default-srcset")),this._setImgAttributes(f,{src:h,srcset:i,alt:f.getAttribute("data-alt")});return l}}}(window);picturePolyfill.initialize(),picturePolyfill.parse(); \ No newline at end of file diff --git a/src/picturePolyfill.js b/src/picturePolyfill.js index 2b424fd..20e69db 100644 --- a/src/picturePolyfill.js +++ b/src/picturePolyfill.js @@ -110,7 +110,7 @@ var picturePolyfill = (function (w) { breakPoint = -1; if (srcset === null || srcset === '' || typeof srcset === 'undefined') { - return null; + return ""; } array = this._getSrcsetArray(srcset); @@ -165,8 +165,7 @@ var picturePolyfill = (function (w) { */ _setImgAttributes: function (pictureElement, attributes) { var imageElements = pictureElement.getElementsByTagName('img'), - imgEl, originalImgSrc, originalImgSrcset, - givenSrcAttribute, givenSrcsetAttribute, + imgEl, givenSrcAttribute, givenSrcsetAttribute, srcToSet, srcsetToSet; function _setAttributeIfDifferent(element, attribute, value) { @@ -179,25 +178,21 @@ var picturePolyfill = (function (w) { return false; } - // Setting repeated usage variables - imgEl = imageElements[0]; - originalImgSrc = imgEl.getAttribute('data-original-src'); - originalImgSrcset = imgEl.getAttribute('data-original-srcset'); - givenSrcAttribute = attributes.src; - givenSrcsetAttribute = attributes.srcset; - // Set original img tag's src and srcset in a data attribute - if (!originalImgSrc) { + imgEl = imageElements[0]; + if (!imgEl.getAttribute('data-original-src')) { _setAttributeIfDifferent(imgEl, 'data-original-src', imgEl.getAttribute('src')); _setAttributeIfDifferent(imgEl, 'data-original-srcset', imgEl.getAttribute('srcset')); } // Set srcToSet and srcsetToSet depending on the given src/srcset attributes // If none are given, use original ones - // If both ore one are given, them (even if one is null) + // If both ore one are given, use them (even if one is null) + givenSrcAttribute = attributes.src; + givenSrcsetAttribute = attributes.srcset; if (!givenSrcAttribute && !givenSrcsetAttribute) { - srcToSet = originalImgSrc; - srcsetToSet = originalImgSrcset; + srcToSet = imgEl.getAttribute('data-original-src'); + srcsetToSet = imgEl.getAttribute('data-original-srcset'); } else { srcToSet = givenSrcAttribute; srcsetToSet = givenSrcsetAttribute; diff --git a/test/picturePolyfill.qunit.js b/test/picturePolyfill.qunit.js index 46e00c2..c868708 100644 --- a/test/picturePolyfill.qunit.js +++ b/test/picturePolyfill.qunit.js @@ -1,10 +1,8 @@ /* -* TODO: Test cases with and sources matching or not matching -* -* TODO: Also read the srcset property on the img tag, in every test! -* -* TODO: Test no double ajax calls: IMG with empty src="" + data-default-src set -* */ + * TODO: Also read the srcset property on the img tag, in every test! + * + * TODO: Test no double ajax calls: IMG with empty src="" + data-default-src set + * */ module("picturePolyfill", { setup: function () { @@ -86,15 +84,15 @@ test("_getSrcFromSrcset correct behaviour, empty srcset", function () { else { srcset = ""; errMsg = "If srcset is empty, empty value must be returned"; - strictEqual(picturePolyfill._getSrcFromSrcset(srcset, -1), null, errMsg); - strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 0), null, errMsg); - strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 1), null, errMsg); + strictEqual(picturePolyfill._getSrcFromSrcset(srcset, -1), "", errMsg); + strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 0), "", errMsg); + strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 1), "", errMsg); srcset = null; errMsg = "If srcset is null, null value must be returned"; - strictEqual(picturePolyfill._getSrcFromSrcset(srcset, -1), null, errMsg); - strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 0), null, errMsg); - strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 1), null, errMsg); + strictEqual(picturePolyfill._getSrcFromSrcset(srcset, -1), "", errMsg); + strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 0), "", errMsg); + strictEqual(picturePolyfill._getSrcFromSrcset(srcset, 1), "", errMsg); } }); @@ -148,17 +146,17 @@ test("_getSrcsetArray correct behaviour, correct srcset format", function () { // Triple with decimals srcset = "http://placehold.it/4x4, http://placehold.it/6x6 1.5x, http://placehold.it/8x8 2x"; expected = [ - {pxr: 1, src: "http://placehold.it/4x4"}, + {pxr: 1, src: "http://placehold.it/4x4"}, {pxr: 1.5, src: "http://placehold.it/6x6"}, - {pxr: 2, src: "http://placehold.it/8x8"} + {pxr: 2, src: "http://placehold.it/8x8"} ]; deepEqual(picturePolyfill._getSrcsetArray(srcset), expected, "Triple with decimals"); // Double with 1x and 3x srcset = "http://placehold.it/4x4, http://placehold.it/12x12 3x"; expected = [ - {pxr: 1, src: "http://placehold.it/4x4"}, - {pxr: 3, src: "http://placehold.it/12x12"} + {pxr: 1, src: "http://placehold.it/4x4"}, + {pxr: 3, src: "http://placehold.it/12x12"} ]; deepEqual(picturePolyfill._getSrcsetArray(srcset), expected, "Double with 1x and 3x"); @@ -166,7 +164,7 @@ test("_getSrcsetArray correct behaviour, correct srcset format", function () { srcset = "http://placehold.it/2x2 .5x, http://placehold.it/4x4"; expected = [ {pxr: 0.5, src: "http://placehold.it/2x2"}, - {pxr: 1, src: "http://placehold.it/4x4"} + {pxr: 1, src: "http://placehold.it/4x4"} ]; deepEqual(picturePolyfill._getSrcsetArray(srcset), expected, "Double with .5x and 1x"); @@ -174,7 +172,7 @@ test("_getSrcsetArray correct behaviour, correct srcset format", function () { srcset = "http://placehold.it/2x2 0.5x, http://placehold.it/4x4"; expected = [ {pxr: 0.5, src: "http://placehold.it/2x2"}, - {pxr: 1, src: "http://placehold.it/4x4"} + {pxr: 1, src: "http://placehold.it/4x4"} ]; deepEqual(picturePolyfill._getSrcsetArray(srcset), expected, "Double with 0.5x and 1x, leading 0"); } @@ -532,7 +530,7 @@ test("parse() resulting image sources - without MQ support", function () { \ '); - if (!picturePolyfill._mqSupport) { // EXCLUDING OLD IE FROM THIS TESTS + if (!picturePolyfill._mqSupport) { // EXCLUDING OLD IE FROM THIS TESTS - but why?! ok(true); } else { @@ -735,9 +733,68 @@ test("parse() with readFromCache true, then false", function () { picturePolyfill._mqSupport = initial_areMediaQueriesSupported; picturePolyfill._pxRatio = initial_pixelRatio; } +}); + +test("parse() with contained img having both src and srcset attributes set", function () { + + var images, img1src, img1srcset, img2src, img2srcset, errMsg; + + $('body').append('
\ + \ + \ + A\ + \ + \ + \ + A\ + \ +
'); + + picturePolyfill.initialize(); + + var initial_pixelRatio = picturePolyfill._pxRatio; + + picturePolyfill._pxRatio = 2; + + // Matching sources + picturePolyfill.parse(document); + + images = document.getElementsByTagName('img'); + + img1src = images[0].getAttribute('src'); + img1srcset = images[0].getAttribute('srcset'); + + errMsg = "Img src and srcset should have changed"; + if (picturePolyfill._mqSupport) { + strictEqual(img1src, 'http://placehold.it/8x8', errMsg); + strictEqual(img1srcset, 'http://placehold.it/4x4, http://placehold.it/8x8 2x', errMsg); + } + else { + strictEqual(img1src, 'http://placehold.it/2x2', errMsg); + strictEqual(img1srcset, null, errMsg); + } + + // Not matching sources + img2src = images[1].getAttribute('src'); + img2srcset = images[1].getAttribute('srcset'); + + // TODO: FIX - CURRENTLY RETURNS NULL SRC AND SRCSET + + errMsg = "Img src and srcset shouldn't have changed"; + if (picturePolyfill._mqSupport) { + strictEqual(img2src, 'http://placehold.it/2x2', errMsg); + strictEqual(img2srcset, 'http://placehold.it/2x2, http://placehold.it/4x4 2x', errMsg); + } + else { + strictEqual(img2src, 'http://placehold.it/2x2', errMsg); + strictEqual(img2srcset, null, errMsg); + } + + picturePolyfill._pxRatio = initial_pixelRatio; }); + test("call parse won't give errors when polyfill isn't required", function () { this.spy(picturePolyfill, "parse"); picturePolyfill.initialize();