Sumit has uploaded a new change for review. https://gerrit.wikimedia.org/r/228785
Change subject: WikidataPageBanner implement srcset polyfill ...................................................................... WikidataPageBanner implement srcset polyfill Implement a polyfill for srcset attribute which presently has limited support. Set default banner image as an image of size 640px to avoid unnecessary loading of a large image. Change-Id: Ic8f2bbdabe69b9da32acbdf1e13e03c912eae82a --- M extension.json M includes/WikidataPageBanner.hooks.php A resources/ext.WikidataPageBanner.srcsetPolyfill/ext.WikidataPageBanner.srcsetPolyfill.js 3 files changed, 140 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikidataPageBanner refs/changes/85/228785/1 diff --git a/extension.json b/extension.json index ab4ff9d..2f6e2c8 100644 --- a/extension.json +++ b/extension.json @@ -48,6 +48,16 @@ "mobile" ], "position": "top" + }, + "ext.WikidataPageBanner.srcsetPolyfill": { + "scripts": [ + "ext.WikidataPageBanner.srcsetPolyfill/ext.WikidataPageBanner.srcsetPolyfill.js" + ], + "targets": [ + "desktop", + "mobile" + ], + "position": "bottom" } }, "ResourceFileModulePaths": { diff --git a/includes/WikidataPageBanner.hooks.php b/includes/WikidataPageBanner.hooks.php index 6465701..0fd5dff 100644 --- a/includes/WikidataPageBanner.hooks.php +++ b/includes/WikidataPageBanner.hooks.php @@ -26,6 +26,7 @@ // only add banner and styling if valid banner generated if ( $banner !== null ) { $out->addModuleStyles( 'ext.WikidataPageBanner' ); + $out->addModules( 'ext.WikidataPageBanner.srcsetPolyfill' ); if ( isset( $params['toc'] ) ) { $out->addModuleStyles( 'ext.WikidataPageBanner.toc.styles' ); } @@ -211,7 +212,7 @@ // create full src set from individual urls, separated by comma $srcset = implode( ',', $srcset ); // use largest image url as src attribute - $bannerurl = $urls[count( $urls ) - 1]; + $bannerurl = $urls[1]; $bannerfile = Title::newFromText( "File:$bannername" ); $templateParser = new TemplateParser( __DIR__ . '/../templates' ); $options['bannerfile'] = $bannerfile->getLocalUrl(); diff --git a/resources/ext.WikidataPageBanner.srcsetPolyfill/ext.WikidataPageBanner.srcsetPolyfill.js b/resources/ext.WikidataPageBanner.srcsetPolyfill/ext.WikidataPageBanner.srcsetPolyfill.js new file mode 100644 index 0000000..b309c6a --- /dev/null +++ b/resources/ext.WikidataPageBanner.srcsetPolyfill/ext.WikidataPageBanner.srcsetPolyfill.js @@ -0,0 +1,128 @@ +( function( mw, $ ) { + /** + * Returns whether or not srcset attribute is supported by this browser + * @return bool true if srcset is supported, otherwise false + */ + function isSrcsetSupported() { + return 'srcset' in new Image(); + } + + /** + * Parses the srcset="" attribute and forms an array of type [{url:"",descriptor:""}] + * @return {array} Array of objects each of which contains a url of image and its corresponding + * size + */ + function parseSrcset( srcset ) { + var srcSet = [], + url, + desc, + separator, + position; + // remove any whitespaces from the end + srcset = srcset.trim(); + while ( srcset.indexOf( ',' ) !== -1 ) { + // get index of space which marks end of url part + position = srcset.indexOf( ' ' ); + // url will be the part of string till first whitespace + url = srcset.slice(0, position); + while ( srcset.charAt( position ) === ' ' ) { + position++; + } + desc = ''; + // get position of next COMMA ',' + separator = srcset.indexOf( ',' ); + // get the descriptor which is only 'w' in the extension currently + desc = srcset.slice( position, separator ); + srcset = srcset.slice( separator + 1 ); + srcSet.push( { + url: url, + descriptor: desc + } ); + } + // parse last url + position = srcset.indexOf( ' ' ); + // url will be the part of string till first whitespace + url = srcset.slice(0, position); + while ( srcset.charAt( position ) === ' ' ) { + position++; + } + desc = ''; + desc = srcset.slice( position, separator ); + srcset = srcset.slice( separator + 1 ); + srcSet.push( { + url: url, + descriptor: desc + } ); + return srcSet; + } + + /** + * Parses descriptor string and returns an object of {x:_,w:_,h:_} values + * @param {string} desc Descriptor string + * @return {object} Object containing keys out of x,w,h and their corresponding values + */ + function parseDesc( desc ) { + var descriptors = desc.split(/\s/), + result = {}, + descriptor, + qualifier, + val, + INT_REGEXP = /^[0-9]+$/; + // traverse descriptor string + for (var i = 0; i < descriptors.length; i++) { + descriptor = descriptors[i]; + if ( descriptor.length > 0 ) { + // get qualifier which is x,w or h + qualifier = descriptor[ descriptor.length - 1 ]; + //get value part + val = descriptor.substring( 0, descriptor.length-1 ); + // value might be int or float depending on qualifier + var intVal = parseInt( val, 10 ); + var floatVal = parseFloat( val ); + if ( val.match( INT_REGEXP ) && qualifier === 'w' ) { + result[qualifier] = intVal; + } else if ( val.match( INT_REGEXP ) && qualifier === 'h' ) { + result[qualifier] = intVal; + } else if ( !isNaN( floatVal ) && qualifier === 'x') { + result[qualifier] = floatVal; + } + } + } + return result; + } + + /** + * Returns the url of the best size image out of those present in srcset, taking into + * consideration screen size and device pixel ratio + * @return {string} Url of image of best size + */ + function getBestImage() { + var srcset = $( '.wpb-banner-image' ).attr( 'srcset' ), + srcSet, + imageSizeMultiplier, + apparentWidth, + bestImage = null; + imageSizeMultiplier = ( window.devicePixelRatio && window.devicePixelRatio > 1 ) ? + window.devicePixelRatio : 1; + apparentWidth = $( '.ext-wpb-pagebanner' ).width() * imageSizeMultiplier; + srcSet = parseSrcset( srcset ); + // split the descriptor string into an object having 'x', 'w', 'h' as its keys and look for + // best image size + for ( var index in srcSet ) { + var descriptor = srcSet[index].descriptor; + descriptor = parseDesc( descriptor ); + srcSet[index].descriptor = descriptor; + // set best image as image of size immediately larger than apparentWidth + // WikidataPageBanner only parses 'w' descriptor and sets image size + if ( descriptor.w && descriptor.w > apparentWidth && !bestImage ) { + bestImage = srcSet[index].url; + } + } + return bestImage; + } + + if ( !isSrcsetSupported() ) { + var bestImage = getBestImage(); + $( '.wpb-banner-image' ).attr( 'src', bestImage ); + } +}( mediaWiki, jQuery ) ); -- To view, visit https://gerrit.wikimedia.org/r/228785 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic8f2bbdabe69b9da32acbdf1e13e03c912eae82a Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/WikidataPageBanner Gerrit-Branch: master Gerrit-Owner: Sumit <asthana.sumi...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits