diff --git a/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php b/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php index 4b93dc5..b41413c 100644 --- a/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php +++ b/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php @@ -71,6 +71,7 @@ public function form(array $form, array &$form_state) { ); $image_styles = image_style_options(TRUE); + $image_styles[PICTURE_EMPTY_IMAGE] = t('- empty image -'); foreach ($picture_mapping->mappings as $breakpoint_id => $mapping) { foreach ($mapping as $multiplier => $image_style) { $label = $multiplier . ' ' . $picture_mapping->breakpointGroup->breakpoints[$breakpoint_id]->name . ' [' . $picture_mapping->breakpointGroup->breakpoints[$breakpoint_id]->mediaQuery . ']'; diff --git a/core/modules/picture/picture.module b/core/modules/picture/picture.module index 60d0f5b..36fb566 100644 --- a/core/modules/picture/picture.module +++ b/core/modules/picture/picture.module @@ -8,6 +8,8 @@ use Drupal\picture\Plugin\Core\Entity\PictureMapping; use \Drupal\Core\Template\Attribute; +define('PICTURE_EMPTY_IMAGE', '_empty image_'); + /** * Implements hook_help(). */ @@ -243,7 +245,7 @@ function theme_picture($variables) { // Fallback image, output as source with media query. $sources[] = array( - 'src' => image_style_url($variables['style_name'], $variables['uri']), + 'src' => _picture_image_style_url($variables['style_name'], $variables['uri']), 'dimensions' => picture_get_image_dimensions($variables), ); @@ -262,7 +264,7 @@ function theme_picture($variables) { // Only one image, use src. if (count($new_sources) == 1) { $sources[] = array( - 'src' => image_style_url($new_sources[0]['style_name'], $new_sources[0]['uri']), + 'src' => _picture_image_style_url($new_sources[0]['style_name'], $new_sources[0]['uri']), 'dimensions' => picture_get_image_dimensions($new_sources[0]), 'media' => $breakpoint->mediaQuery, ); @@ -271,7 +273,7 @@ function theme_picture($variables) { // Mutliple images, use srcset. $srcset = array(); foreach ($new_sources as $new_source) { - $srcset[] = image_style_url($new_source['style_name'], $new_source['uri']) . ' ' . $new_source['#multiplier']; + $srcset[] = _picture_image_style_url($new_source['style_name'], $new_source['uri']) . ' ' . $new_source['#multiplier']; } $sources[] = array( 'srcset' => implode(', ', $srcset), @@ -289,7 +291,7 @@ function theme_picture($variables) { $attributes[$key] = $variables[$key]; } } - $output[] = ''; + $output[] = ''; // Add source tags to the output. foreach ($sources as $source) { @@ -298,7 +300,7 @@ function theme_picture($variables) { // Output the fallback image. $output[] = ''; - $output[] = ''; + $output[] = ''; return implode("\n", $output); } } @@ -321,17 +323,14 @@ function theme_picture_source($variables) { $output = array(); if (isset($variables['media']) && !empty($variables['media'])) { if (!isset($variables['srcset'])) { - $output[] = ''; - $output[] = ''; + $output[] = ''; } elseif (!isset($variables['src'])) { - $output[] = ''; - $output[] = ''; + $output[] = ''; } } else { - $output[] = ''; - $output[] = ''; + $output[] = ''; } return implode("\n", $output); } @@ -356,7 +355,25 @@ function picture_get_image_dimensions($variables) { 'height' => $variables['height'], ); - image_style_transform_dimensions($variables['style_name'], $dimensions); + if ($variables['style_name'] == PICTURE_EMPTY_IMAGE) { + $dimensions = array( + 'width' => 1, + 'height' => 1, + ); + } + else { + image_style_transform_dimensions($variables['style_name'], $dimensions); + } return $dimensions; } + +/** + * Wrapper around image_style_url() so we can return an empty image. + */ +function _picture_image_style_url($style_name, $path) { + if ($style_name == PICTURE_EMPTY_IMAGE) { + return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; + } + return image_style_url($style_name, $path); +} diff --git a/core/modules/picture/picturefill/picturefill.js b/core/modules/picture/picturefill/picturefill.js index 8df8eb9..ebcdd82 100644 --- a/core/modules/picture/picturefill/picturefill.js +++ b/core/modules/picture/picturefill/picturefill.js @@ -1,110 +1,66 @@ /*jshint loopfunc: true, browser: true, curly: true, eqeqeq: true, expr: true, forin: true, latedef: true, newcap: true, noarg: true, trailing: true, undef: true, unused: true */ /*! Picturefill - Author: Scott Jehl, 2012 | License: MIT/GPLv2 */ -(function( w ){ +(function(w, parent){ // Enable strict mode. "use strict"; - // Test if `` is supported natively, if so, exit. - if (!!(w.document.createElement('picture') && w.document.createElement('source') && w.HTMLPictureElement)) { - return; - } - - w.picturefill = function() { + w.picturefill = function(parent) { // Copy attributes from the source to the destination. function _copyAttributes(src, tar) { - if (src.getAttribute('width') && src.getAttribute('height')) { - tar.width = src.getAttribute('width'); - tar.height = src.getAttribute('height'); + if (src.getAttribute('data-width') && src.getAttribute('data-height')) { + tar.width = src.getAttribute('data-width'); + tar.height = src.getAttribute('data-height'); + } + else { + tar.removeAttribute('width'); + tar.removeAttribute('height'); } } // Get all picture tags. - var ps = w.document.getElementsByTagName('picture'); + if (!parent || !parent.getElementsByTagName) { + parent = w.document; + } + var ps = parent.getElementsByTagName('span'); // Loop the pictures. for (var i = 0, il = ps.length; i < il; i++ ) { - var sources = ps[i].getElementsByTagName('source'); - var picImg = null; - var matches = []; - - // If no sources are found, they're likely erased from the DOM. - // Try finding them inside comments. - if (!sources.length) { - var picText = ps[i].innerHTML; - var frag = w.document.createElement('div'); - // For IE9, convert the source elements to divs. - var srcs = picText.replace(/(<)source([^>]+>)/gmi, '$1div$2').match(/]+>/gmi); - - frag.innerHTML = srcs.join(''); - sources = frag.getElementsByTagName('div'); - } - - // See which sources match. - for (var j = 0, jl = sources.length; j < jl; j++ ) { - var media = sources[j].getAttribute('media'); - // If there's no media specified or the media query matches, add it. - if (!media || (w.matchMedia && w.matchMedia(media).matches)) { - matches.push(sources[j]); - } - } - - if (matches.length) { - // Grab the most appropriate (last) match. - var match = matches.pop(); - var srcset = match.getAttribute('srcset'); - - // Find any existing img element in the picture element. - picImg = ps[i].getElementsByTagName('img')[0]; - - // Add a new img element if one doesn't exists. - if (!picImg) { - picImg = w.document.createElement('img'); - picImg.alt = ps[i].getAttribute('alt'); - ps[i].appendChild(picImg); + if (ps[i].getAttribute('data-picture') !== null) { + var sources = ps[i].getElementsByTagName('span'); + var picImg = null; + var matches = []; + + // See 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 the media query matches, add it. + if (!media || (w.matchMedia && w.matchMedia(media).matches)) { + matches.push(sources[j]); + } } - // Source element uses a srcset. - if (srcset) { - var screenRes = w.devicePixelRatio || 1; - // Split comma-separated `srcset` sources into an array. - sources = srcset.split(', '); + if (matches.length) { + // Grab the most appropriate (last) match. + var match = matches.pop(); - // Loop through each source/resolution in srcset. - for (var res = sources.length, r = res - 1; r >= 0; r-- ) { - // Remove any leading whitespace, then split on spaces. - var source = sources[ r ].replace(/^\s*/, '').replace(/\s*$/, '').split(' '); - // Parse out the resolution for each source in `srcset`. - var resMatch = parseFloat(source[1], 10); + // Find any existing img element in the picture element. + picImg = ps[i].getElementsByTagName('img')[0]; - if (screenRes >= resMatch) { - if (picImg.getAttribute('src') !== source[0]) { - var newImg = document.createElement('img'); + // Add a new img element if one doesn't exists. + if (!picImg) { + picImg = w.document.createElement('img'); + picImg.alt = ps[i].getAttribute('data-alt') || ''; + picImg.title = ps[i].getAttribute('data-title') || ''; + ps[i].appendChild(picImg); + } - newImg.src = source[0]; - // When the image is loaded, set a width equal to that of the - // original’s intrinsic width divided by the screen resolution. - newImg.onload = function() { - // Clone the original image into memory so the width is - // unaffected by page styles. - var w = this.cloneNode(true).width; - if (w > 0) { - this.width = (w / resMatch); - } - }; - // Copy width and height from the source tag to the img element. - _copyAttributes(match, newImg); - picImg.parentNode.replaceChild(newImg, picImg); - } - // We’ve matched, so bail out of the loop here. - break; - } + // Set the source if it's different. + if (picImg.getAttribute('src') !== match.getAttribute('data-src')) { + picImg.src = match.getAttribute('data-src'); + _copyAttributes(match, picImg); } - } else { - // No srcset used, so just use the 'src' value. - picImg.src = match.getAttribute('src'); - // Copy width and height from the source tag to the img element. - _copyAttributes(match, picImg); } } } @@ -123,4 +79,4 @@ else if (w.attachEvent) { w.attachEvent('onload', w.picturefill); } -})(this); +})(this); \ No newline at end of file