Skip to content

Commit

Permalink
Merge branch 'master' into gh-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
verlok committed Mar 13, 2014
2 parents 2a73ba2 + 4d01312 commit 2ab23c6
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 70 deletions.
11 changes: 11 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "pictyrePolyfill",
"version": "1.0.1",
"main": "",
"ignore": [
".idea",
".gitignore"
],
"dependencies": {},
"devDependencies": {}
}
1 change: 1 addition & 0 deletions picturePolyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
if (typeof arrayOrString === 'string') {
return arrayOrString;
}
position = Math.ceil(position);
while (arrayOrString[position]===undefined && position>0) {
position-=1;
}
Expand Down
33 changes: 13 additions & 20 deletions usingPictureMarkup/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,32 @@ <h1>Responsive images using PicturePolyfill - Demo</h1>
<p>The following link contains two <strong>responsive images</strong> created using a <code>&lt;span&gt;</code> element, inline JSON (instead of <code>&lt;source&gt;</code> markup), and the <a href="https://github.com/verlok/picturePolyfill">picturePolyfill</a> script.</p>
</div>
<div class="element">
<h2>Without HD (Retina) display support</h2>
<a href="#someLink2">
<picture data-alt="A beautiful responsive image" data-picture='[
{"srcset": "http://demo.api.pixtulate.com/demo/large-2.jpg?w=480"},
{"srcset": "http://demo.api.pixtulate.com/demo/large-2.jpg?w=512", "media": "(min-width: 481px)"},
{"srcset": "http://demo.api.pixtulate.com/demo/large-2.jpg?w=960", "media": "(min-width: 1025px)"}
]'>
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=480">
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=512" media="(min-width: 481px)">
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=960" media="(min-width: 1025px)">
<h2>With HD (Retina) display support</h2>
<a href="#someLink1">
<picture data-alt="A beautiful responsive image">
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=480, http://demo.api.pixtulate.com/demo/large-2.jpg?w=960 2x"/>
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=512, http://demo.api.pixtulate.com/demo/large-2.jpg?w=1024 2x" media="(min-width: 481px)"/>
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=960, http://demo.api.pixtulate.com/demo/large-2.jpg?w=1920 2x" media="(min-width: 1025px)"/>
<noscript>
<img src="http://demo.api.pixtulate.com/demo/large-2.jpg?w=512" alt="A beautiful responsive image"/>
</noscript>
</picture>
</a>
</div>
<div class="element">
<h2>With HD (Retina) display support</h2>
<a href="#someLink1">
<picture data-alt="A beautiful responsive image" data-picture='[
{"srcset": ["http://demo.api.pixtulate.com/demo/large-2.jpg?w=480", "http://demo.api.pixtulate.com/demo/large-2.jpg?w=960"]},
{"srcset": ["http://demo.api.pixtulate.com/demo/large-2.jpg?w=512", "http://demo.api.pixtulate.com/demo/large-2.jpg?w=1025"], "media": "(min-width: 481px)"},
{"srcset": ["http://demo.api.pixtulate.com/demo/large-2.jpg?w=960", "http://demo.api.pixtulate.com/demo/large-2.jpg?w=1920"], "media": "(min-width: 1025px)"}
]'>
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=480, http://demo.api.pixtulate.com/demo/large-2.jpg?w=960 2x">
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=512, http://demo.api.pixtulate.com/demo/large-2.jpg?w=1024 2x" media="(min-width: 481px)">
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=960, http://demo.api.pixtulate.com/demo/large-2.jpg?w=1920 2x" media="(min-width: 1025px)">
<h2>Without HD (Retina) display support</h2>
<a href="#someLink2">
<picture data-alt="A beautiful responsive image">
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=480"/>
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=512" media="(min-width: 481px)"/>
<source srcset="http://demo.api.pixtulate.com/demo/large-2.jpg?w=960" media="(min-width: 1025px)"/>
<noscript>
<img src="http://demo.api.pixtulate.com/demo/large-2.jpg?w=512" alt="A beautiful responsive image"/>
</noscript>
</picture>
</a>
</div>

<div class="outro">
<p>Real time server side scaling is provided by <a href="http://www.pixtulate.com">Pixtulate</a>.</p>
</div>
Expand Down
148 changes: 98 additions & 50 deletions usingPictureMarkup/picturePolyfill.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,60 @@
/* PicturePolyfill - Responsive Images that work today. (and mimic the proposed Picture element with span elements). Author: Andrea Verlicchi | License: MIT/GPLv2 */

(function() {
(function(w) {

"use strict";

var timerId,
pixelRatio = window.devicePixelRatio || 1, // The pixel density (2 is for HD aka Retina displays)
mediaQueriesSupported = window.matchMedia && window.matchMedia("only all") !== null && window.matchMedia("only all").matches;
pixelRatio = w.devicePixelRatio || 1, // The pixel density (2 is for HD aka Retina displays)
mediaQueriesSupported = w.matchMedia && w.matchMedia("only all") !== null && w.matchMedia("only all").matches;

/**
* Activate picture and source tag support for IE8
*/

document.createElement("picture");
document.createElement("source");


/**
* Returns a hash density > src
*/

function getSrcSetHash(srcSetAttribute) {
var hash = {},
sources = srcSetAttribute.split(',');

for (var i=0, len=sources.length; i<len; i+=1) {
var srcAndDensity = sources[i].trim().split(' ');
var src = srcAndDensity[0].trim();
var density = (parseInt(srcAndDensity[1], 10) || 1).toString();
hash[density] = src;
}

return hash;
}


/**
* Returns the proper src from the srcSet property
* If arrayOrString is a string, returns it
* else get the first valid element from passed position to the left
* @param arrayOrString
* Get the first valid element from passed position to the left
* @param srcSetArray
* @param position
* @returns {*}
* @returns {string}
*/

function getSrcFromSrcSet(arrayOrString, position) {
if (typeof arrayOrString === 'string') {
return arrayOrString;
}
while (arrayOrString[position]===undefined && position>0) {
function getSrcFromSrcSetArray(srcSetArray, position) {
while (srcSetArray[position]===undefined && position>0) {
position-=1;
}
return arrayOrString[position];
return srcSetArray[position];
}


/**
* Loop through every element of the dataPicture array, check if the media query applies and,
* if so, get the src element from the srcSet property based depending on pixel ratio
* @param dataPicture
* @param dataPicture {element}
* @returns {string}
*/

Expand All @@ -40,8 +63,8 @@

for (var i=0, len=dataPicture.length; i<len; i+=1) {
media = dataPicture[i].media;
if (!media || window.matchMedia(media).matches) {
matchedSrc = getSrcFromSrcSet(dataPicture[i].srcset, pixelRatio-1);
if (!media || w.matchMedia(media).matches) {
matchedSrc = getSrcFromSrcSetArray(dataPicture[i].srcset, pixelRatio);
}
}
return matchedSrc;
Expand All @@ -50,7 +73,7 @@

/**
* Search for the "standard: true" image in the array
* @param dataPicture
* @param dataPicture {element}
* @returns {string}
*/

Expand All @@ -63,19 +86,20 @@
break;
}
}
return getSrcFromSrcSet(dataElement.srcset, 0);
return getSrcFromSrcSetArray(dataElement.srcset, 0);
}


/**
* Set the src attribute of the first image element inside passed imageHolder
* if the image doesn't exist, creates it, sets its alt attribute, and appends it to imageHolder
* @param imageHolder
* Set the src attribute of the first image element inside passed pictureElement
* if the image doesn't exist, creates it, sets its alt attribute, and appends it to pictureElement
* @param pictureElement
* @param srcAttribute
*/

function createOrUpdateImage(imageHolder, srcAttribute) {
function createOrUpdateImage(pictureElement, srcAttribute) {
var imageElements, imageElement;
imageElements = imageHolder.getElementsByTagName('img');
imageElements = pictureElement.getElementsByTagName('img');

// If image already exist, use it
if (imageElements.length) {
Expand All @@ -84,10 +108,34 @@
// Else create the image
else {
imageElement = document.createElement('img');
imageElement.setAttribute('alt', imageHolder.getAttribute('data-alt'));
imageElement.setAttribute('alt', pictureElement.getAttribute('data-alt'));
imageElement.setAttribute('src', srcAttribute);
imageHolder.appendChild(imageElement);
pictureElement.appendChild(imageElement);
}
}


/**
* Parses the picture element looking for sources elements, then
* generate the array or string for the SrcSetArray
* @param element the starting element to parse DOM into. If not passed, it parses the whole document.
*/

function parseSources(pictureElement) {
var arr = [],
sourceElements = pictureElement.getElementsByTagName('source');

for (var i=0, len = sourceElements.length; i<len; i+=1) {
var sourceElement = sourceElements[i];
var media = sourceElement.getAttribute('media');
var srcset = getSrcSetHash(sourceElement.getAttribute('srcset'));
arr.push({
'media': media,
'srcset': srcset
});
}

return arr;
}

/**
Expand All @@ -96,24 +144,24 @@
* @param element the starting element to parse DOM into. If not passed, it parses the whole document.
*/

function parseDOM(element) {
var pictureData, imageHolder,
imageHolders = (element || document).querySelectorAll('[data-picture]');
function parsePictures(element) {
var pictureData, pictureElement,
pictureElements = element.getElementsByTagName('picture');

// Finding all the elements with data-image
for (var i=0, len=imageHolders.length; i<len; i+=1) {
imageHolder = imageHolders[i];
try {
pictureData = JSON.parse(imageHolder.getAttribute('data-picture'));
for (var i=0, len=pictureElements.length; i<len; i+=1) {
pictureElement = pictureElements[i];
//try {
pictureData = parseSources(pictureElement);
// Take the source from the matched media, or standard media
// Update the image, or create it
createOrUpdateImage(imageHolder, (mediaQueriesSupported) ?
createOrUpdateImage(pictureElement, (mediaQueriesSupported) ?
getSrcAttributeFromData(pictureData) :
getStandardImageFromData(pictureData));
}
catch (e) {
window.console.log(e);
}
// }
//catch (e) {
// w.console.log(e);
//}
}
}

Expand All @@ -122,29 +170,29 @@
* @type {Function}
*/

window.picturePolyfill = (!document.querySelectorAll) ? function(){} : function(){
parseDOM(document);
w.picturePolyfill = (!document.querySelectorAll) ? function(){} : function(element){
parsePictures(element || document);
};

/**
* Manage resize event calling the parseDOM function
* Manage resize event calling the parsePictures function
* only if they've passed 100 milliseconds between a resize event and another
* to avoid the script to slower the browser on animated resize or browser edge dragging
*/

if (window.addEventListener) {
window.addEventListener('resize', function() {
if (w.addEventListener) {
w.addEventListener('resize', function() {
clearTimeout(timerId);
timerId = setTimeout(window.picturePolyfill, 100);
timerId = setTimeout(w.picturePolyfill, 100);
});
window.addEventListener('DOMContentLoaded', function(){
window.picturePolyfill();
window.removeEventListener('load', window.picturePolyfill);
w.addEventListener('DOMContentLoaded', function(){
w.picturePolyfill();
w.removeEventListener('load', w.picturePolyfill);
});
window.addEventListener('load', window.picturePolyfill);
w.addEventListener('load', w.picturePolyfill);
}
else if (window.attachEvent) {
window.attachEvent('onload', window.picturePolyfill);
else if (w.attachEvent) {
w.attachEvent('onload', w.picturePolyfill);
}

}());
}(this));

0 comments on commit 2ab23c6

Please sign in to comment.