Properly create the <svg> and <image> elements for thumbnails

We have to be careful about the namespaces here, and then we don't
need the awful `.html( .html() )` hack. (I honestly have no idea
why that even worked for some browsers, it really shouldn't have.
The comment next to it is wrong.)

* Construct the 'svg:svg' element with the right namespace
* Set 'xlink:href' attribute on 'svg:image' element with the right namespace

Doing this correctly makes the thumbnails work in Opera 12, and it also
works as before in (at least) Chromium 57, Firefox 53, IE 11 and Edge.

I can't find out what version of Safari the other hack here was
supposed to apply to, but the code was wrong in both cases, and the
hack was mistakenly also applied to modern Chromium.

Useful resources for dealing with SVG embedded in HTML while scripting:

* http://stackoverflow.com/questions/6701705/programmatically-creating-an-svg-image-element-with-javascript
  * http://jsfiddle.net/UVFBj/8/
* https://www.w3.org/Graphics/SVG/WG/wiki/Href#xlink:href

Bug: T161799
Change-Id: I30b2a1291811296424018e013bd07055ae7551d7
This commit is contained in:
Bartosz Dziewoński 2017-03-30 16:14:38 +02:00
parent 1e199b67f0
commit 7967ab77ee
3 changed files with 6 additions and 30 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,6 +1,5 @@
var mw = window.mediaWiki,
$ = jQuery,
isSafari = navigator.userAgent.match( /Safari/ ) !== null,
wait = require( './wait' ),
SIZES = {
portraitImage: {
@ -254,17 +253,6 @@ function show( preview, event, behavior ) {
preview.el.appendTo( document.body );
// Hack to "refresh" the SVG so that it's displayed.
//
// Elements get added to the DOM and not to the screen because of different
// namespaces of HTML and SVG.
//
// See http://stackoverflow.com/a/13654655/366138 for more detail.
//
// TODO: Find out how early on in the render that this could be done, e.g.
// createThumbnail?
preview.el.html( preview.el.html() );
layoutPreview( preview, layout );
preview.el.show();
@ -429,14 +417,11 @@ function createThumbnail( rawThumbnail ) {
*/
function createThumbnailElement( className, url, x, y, thumbnailWidth, thumbnailHeight, width, height, clipPath ) {
var $thumbnailSVGImage, $thumbnail,
ns = 'http://www.w3.org/2000/svg',
nsSvg = 'http://www.w3.org/2000/svg',
nsXlink = 'http://www.w3.org/1999/xlink';
// Use createElementNS to create the svg:image tag as jQuery uses
// createElement instead. Some browsers mistakenly map the image tag to
// img tag.
svgElement = document.createElementNS( 'http://www.w3.org/2000/svg', 'image' );
$thumbnailSVGImage = $( svgElement );
$thumbnailSVGImage = $( document.createElementNS( nsSvg, 'image' ) );
$thumbnailSVGImage[ 0 ].setAttributeNS( nsXlink, 'href', url );
$thumbnailSVGImage
.addClass( className )
.attr( {
@ -447,18 +432,9 @@ function createThumbnailElement( className, url, x, y, thumbnailWidth, thumbnail
'clip-path': 'url(#' + clipPath + ')'
} );
// Certain browsers, e.g. IE9, will not correctly set attributes from
// foreign namespaces using Element#setAttribute (see T134979). Apart from
// Safari, all supported browsers can set them using Element#setAttributeNS
// (see T134979).
if ( isSafari ) {
svgElement.setAttribute( 'xlink:href', url );
} else {
svgElement.setAttributeNS( ns, 'xlink:href', url );
}
$thumbnail = $( '<svg>' )
$thumbnail = $( document.createElementNS( nsSvg, 'svg' ) )
.attr( {
xmlns: ns,
xmlns: nsSvg,
width: width,
height: height
} )