mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-12-23 03:23:09 +00:00
79120fc16c
Parsoid added a class and, without it, we get selser complaining about wrappers being modified, similar to T214649. The "image" class is removed since Parsoid never added it (although it now has "mw-file-description" for a similar purpose) and the legacy parser doesn't apply it indiscriminately. It doesn't seem like VE supports editing the |link= media option; it just tries to roundtrip what's there and drops it on edit. The patch here works with that limitation. Galleries are found to drop href's, breaking selser, and should be fixed in a follow up. Bug: T292657 Bug: T303469 Change-Id: I92359048b42d32fe8a0f2cb79cd348cf5f2c56cc
132 lines
4.2 KiB
JavaScript
132 lines
4.2 KiB
JavaScript
/*!
|
|
* VisualEditor ContentEditable MWGalleryImageNode class.
|
|
*
|
|
* @copyright 2011-2020 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* ContentEditable MediaWiki gallery image node.
|
|
*
|
|
* @class
|
|
* @extends ve.ce.BranchNode
|
|
*
|
|
* @constructor
|
|
* @param {ve.dm.MWGalleryImageNode} model Model to observe
|
|
* @param {Object} [config] Configuration options
|
|
*/
|
|
ve.ce.MWGalleryImageNode = function VeCeMWGalleryImageNode( model ) {
|
|
// Parent constructor
|
|
ve.ce.MWGalleryImageNode.super.apply( this, arguments );
|
|
|
|
// DOM hierarchy for MWGalleryImageNode:
|
|
// <li> this.$element (gallerybox)
|
|
// <div> thumbDiv
|
|
// <span> innerDiv
|
|
// <a> a
|
|
// <img> img
|
|
// <a> filenameA (galleryfilename)
|
|
// <figcaption> ve.ce.MWGalleryImageCaptionNode
|
|
|
|
var defaults = mw.config.get( 'wgVisualEditorConfig' ).galleryOptions;
|
|
var attributes = model.getAttributes();
|
|
var galleryMwAttrs = model.parent.getAttributes().mw.attrs;
|
|
|
|
// Putting all this setup in the constructor works because MWGalleryImageNodes are never updated,
|
|
// only created from scratch
|
|
|
|
// These dimensions are different depending on the gallery mode.
|
|
// (This only vaguely approximates the actual rendering.)
|
|
var mode = galleryMwAttrs.mode || defaults.mode;
|
|
var innerDivWidth, innerDivHeight, innerDivMargin, outerDivWidth;
|
|
if ( mode === 'traditional' || mode === 'nolines' || mode === 'slideshow' ) {
|
|
var imagePadding = ( mode === 'traditional' ? 30 : 0 );
|
|
innerDivWidth = parseInt( galleryMwAttrs.widths || defaults.imageWidth ) + imagePadding;
|
|
innerDivHeight = parseInt( galleryMwAttrs.heights || defaults.imageHeight ) + imagePadding;
|
|
if ( mode === 'traditional' ) {
|
|
var imageHeight = parseInt( attributes.height );
|
|
innerDivMargin = ( ( innerDivHeight - imageHeight ) / 2 ) + 'px auto';
|
|
} else {
|
|
innerDivMargin = 0;
|
|
}
|
|
outerDivWidth = innerDivWidth + 8;
|
|
} else {
|
|
innerDivWidth = parseInt( attributes.width );
|
|
innerDivHeight = parseInt( galleryMwAttrs.heights || defaults.imageHeight );
|
|
innerDivMargin = 0;
|
|
outerDivWidth = innerDivWidth + 4;
|
|
}
|
|
|
|
var resourceTitle = mw.Title.newFromText( mw.libs.ve.normalizeParsoidResourceName( attributes.resource ) );
|
|
|
|
this.$element
|
|
.addClass( 'gallerybox' )
|
|
.css( 'width', outerDivWidth + 'px' );
|
|
var $thumbDiv = $( '<div>' )
|
|
.addClass( 'thumb' )
|
|
.css( 'width', innerDivWidth + 'px' )
|
|
.css( 'height', innerDivHeight + 'px' );
|
|
var $innerDiv = $( '<span>' )
|
|
.css( 'margin', innerDivMargin );
|
|
var $a = $( '<a>' );
|
|
var $img = $( '<img>' )
|
|
.attr( 'resource', attributes.resource )
|
|
.attr( 'alt', attributes.altText )
|
|
.attr( 'src', attributes.src )
|
|
.attr( 'height', attributes.height )
|
|
.attr( 'width', attributes.width );
|
|
this.$filenameA = $( '<a>' )
|
|
.attr( 'href', '#' ) // Just to make it look like a link
|
|
.text( resourceTitle ? resourceTitle.getMainText() : attributes.resource )
|
|
.toggleClass( 'oo-ui-element-hidden', galleryMwAttrs.showfilename !== 'yes' );
|
|
|
|
this.$element.prepend(
|
|
$thumbDiv.append(
|
|
$innerDiv.append(
|
|
$a.append(
|
|
$img
|
|
)
|
|
)
|
|
),
|
|
this.$filenameA
|
|
);
|
|
|
|
this.model.parent.connect( this, { attributeChange: 'onGalleryAttributeChange' } );
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.ce.MWGalleryImageNode, ve.ce.BranchNode );
|
|
|
|
/* Static Properties */
|
|
|
|
ve.ce.MWGalleryImageNode.static.name = 'mwGalleryImage';
|
|
|
|
ve.ce.MWGalleryImageNode.static.tagName = 'li';
|
|
|
|
/* Methods */
|
|
|
|
ve.ce.MWGalleryImageNode.prototype.onGalleryAttributeChange = function ( key, from, to ) {
|
|
if ( key !== 'mw' ) {
|
|
return;
|
|
}
|
|
|
|
this.$filenameA.toggleClass( 'oo-ui-element-hidden', to.attrs.showfilename !== 'yes' );
|
|
};
|
|
|
|
ve.ce.MWGalleryImageNode.prototype.getDomPosition = function () {
|
|
// We need to override this because this.$element can have children other than renderings of child
|
|
// CE nodes (specifically, the image, this.$thumbDiv), which throws the calculations out of whack.
|
|
// Luckily, MWGalleryImageNode is very simple and can contain at most one other node: its caption,
|
|
// which is always inserted at the end.
|
|
var domNode = this.$element.last()[ 0 ];
|
|
return {
|
|
node: domNode,
|
|
offset: domNode.childNodes.length
|
|
};
|
|
};
|
|
|
|
/* Registration */
|
|
|
|
ve.ce.nodeFactory.register( ve.ce.MWGalleryImageNode );
|