mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-30 00:55:00 +00:00
65d92173ea
In two cases we were using fragment.getSurface().getFragment() which creates a new fragment from the current selection instead of using the range of the original fragment. Change-Id: Ib41efe2ceb670a125c0c306d143e56f9b9c349e7
727 lines
20 KiB
JavaScript
727 lines
20 KiB
JavaScript
/*!
|
|
* VisualEditor user interface MWMediaEditDialog class.
|
|
*
|
|
* @copyright 2011-2014 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
/*global mw */
|
|
|
|
/**
|
|
* Dialog for editing MediaWiki media objects.
|
|
*
|
|
* @class
|
|
* @extends ve.ui.NodeDialog
|
|
*
|
|
* @constructor
|
|
* @param {Object} [config] Configuration options
|
|
*/
|
|
ve.ui.MWMediaEditDialog = function VeUiMWMediaEditDialog( config ) {
|
|
// Parent constructor
|
|
ve.ui.MWMediaEditDialog.super.call( this, config );
|
|
|
|
// Properties
|
|
this.captionNode = null;
|
|
this.store = null;
|
|
this.scalable = null;
|
|
|
|
// Events
|
|
this.connect( this, { 'ready': 'onReady' } );
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.ui.MWMediaEditDialog, ve.ui.NodeDialog );
|
|
|
|
/* Static Properties */
|
|
|
|
ve.ui.MWMediaEditDialog.static.name = 'mediaEdit';
|
|
|
|
ve.ui.MWMediaEditDialog.static.title =
|
|
OO.ui.deferMsg( 'visualeditor-dialog-media-title' );
|
|
|
|
ve.ui.MWMediaEditDialog.static.icon = 'picture';
|
|
|
|
ve.ui.MWMediaEditDialog.static.defaultSize = 'large';
|
|
|
|
ve.ui.MWMediaEditDialog.static.modelClasses = [ ve.dm.MWBlockImageNode ];
|
|
|
|
ve.ui.MWMediaEditDialog.static.toolbarGroups = [
|
|
// History
|
|
{ 'include': [ 'undo', 'redo' ] },
|
|
// No formatting
|
|
/* {
|
|
'type': 'menu',
|
|
'indicator': 'down',
|
|
'title': OO.ui.deferMsg( 'visualeditor-toolbar-format-tooltip' ),
|
|
'include': [ { 'group': 'format' } ],
|
|
'promote': [ 'paragraph' ],
|
|
'demote': [ 'preformatted', 'heading1' ]
|
|
},*/
|
|
// Style
|
|
{
|
|
'type': 'list',
|
|
'icon': 'text-style',
|
|
'indicator': 'down',
|
|
'title': OO.ui.deferMsg( 'visualeditor-toolbar-style-tooltip' ),
|
|
'include': [ { 'group': 'textStyle' }, 'clear' ],
|
|
'promote': [ 'bold', 'italic' ],
|
|
'demote': [ 'strikethrough', 'code', 'underline', 'clear' ]
|
|
},
|
|
// Link
|
|
{ 'include': [ 'link' ] },
|
|
// Cite
|
|
{
|
|
'type': 'list',
|
|
'label': 'Cite',
|
|
'indicator': 'down',
|
|
'include': [ { 'group': 'cite' } ]
|
|
},
|
|
// No structure
|
|
/* {
|
|
'type': 'bar',
|
|
'include': [ 'number', 'bullet', 'outdent', 'indent' ]
|
|
},*/
|
|
// Insert
|
|
{
|
|
'label': OO.ui.deferMsg( 'visualeditor-toolbar-insert' ),
|
|
'indicator': 'down',
|
|
'include': '*',
|
|
'exclude': [
|
|
{ 'group': 'format' },
|
|
{ 'group': 'structure' },
|
|
'referenceList',
|
|
'gallery'
|
|
],
|
|
'promote': [ 'reference', 'mediaInsert' ],
|
|
'demote': [ 'language', 'specialcharacter' ]
|
|
}
|
|
];
|
|
|
|
ve.ui.MWMediaEditDialog.static.surfaceCommands = [
|
|
'undo',
|
|
'redo',
|
|
'bold',
|
|
'italic',
|
|
'link',
|
|
'clear',
|
|
'underline',
|
|
'subscript',
|
|
'superscript',
|
|
'pasteSpecial'
|
|
];
|
|
|
|
ve.ui.MWMediaEditDialog.static.pasteRules = ve.extendObject(
|
|
ve.copy( ve.init.mw.Target.static.pasteRules ),
|
|
{
|
|
'all': {
|
|
'blacklist': OO.simpleArrayUnion(
|
|
ve.getProp( ve.init.mw.Target.static.pasteRules, 'all', 'blacklist' ) || [],
|
|
[
|
|
// Tables (but not lists) are possible in wikitext with a leading
|
|
// line break but we prevent creating these with the UI
|
|
'list', 'listItem', 'definitionList', 'definitionListItem',
|
|
'table', 'tableCaption', 'tableSection', 'tableRow', 'tableCell'
|
|
]
|
|
),
|
|
// Headings are also possible, but discouraged
|
|
'conversions': {
|
|
'mwHeading': 'paragraph'
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.initialize = function () {
|
|
var altTextFieldset, positionFieldset, borderField, positionField;
|
|
|
|
// Parent method
|
|
ve.ui.MWMediaEditDialog.super.prototype.initialize.call( this );
|
|
|
|
this.$spinner = this.$( '<div>' ).addClass( 've-specialchar-spinner' );
|
|
|
|
// Set up the booklet layout
|
|
this.bookletLayout = new OO.ui.BookletLayout( {
|
|
'$': this.$,
|
|
'outlined': true
|
|
} );
|
|
|
|
this.generalSettingsPage = new OO.ui.PageLayout( 'general', { '$': this.$ } );
|
|
this.advancedSettingsPage = new OO.ui.PageLayout( 'advanced', { '$': this.$ } );
|
|
this.bookletLayout.addPages( [
|
|
this.generalSettingsPage, this.advancedSettingsPage
|
|
] );
|
|
this.generalSettingsPage.getOutlineItem()
|
|
.setIcon( 'parameter' )
|
|
.setLabel( ve.msg( 'visualeditor-dialog-media-page-general' ) );
|
|
this.advancedSettingsPage.getOutlineItem()
|
|
.setIcon( 'parameter' )
|
|
.setLabel( ve.msg( 'visualeditor-dialog-media-page-advanced' ) );
|
|
|
|
// Define fieldsets for image settings
|
|
|
|
// Caption
|
|
this.captionFieldset = new OO.ui.FieldsetLayout( {
|
|
'$': this.$,
|
|
'label': ve.msg( 'visualeditor-dialog-media-content-section' ),
|
|
'icon': 'parameter'
|
|
} );
|
|
|
|
// Alt text
|
|
altTextFieldset = new OO.ui.FieldsetLayout( {
|
|
'$': this.$,
|
|
'label': ve.msg( 'visualeditor-dialog-media-alttext-section' ),
|
|
'icon': 'parameter'
|
|
} );
|
|
|
|
this.altTextInput = new OO.ui.TextInputWidget( {
|
|
'$': this.$
|
|
} );
|
|
|
|
this.altTextInput.$element.addClass( 've-ui-mwMediaEditDialog-altText' );
|
|
|
|
// Build alt text fieldset
|
|
altTextFieldset.$element
|
|
.append( this.altTextInput.$element );
|
|
|
|
// Position
|
|
this.positionInput = new OO.ui.ButtonSelectWidget( {
|
|
'$': this.$
|
|
} );
|
|
this.positionInput.addItems( [
|
|
new OO.ui.ButtonOptionWidget( 'left', {
|
|
'$': this.$,
|
|
'icon': 'align-float-left',
|
|
'label': ve.msg( 'visualeditor-dialog-media-position-left' )
|
|
} ),
|
|
new OO.ui.ButtonOptionWidget( 'center', {
|
|
'$': this.$,
|
|
'icon': 'align-center',
|
|
'label': ve.msg( 'visualeditor-dialog-media-position-center' )
|
|
} ),
|
|
new OO.ui.ButtonOptionWidget( 'right', {
|
|
'$': this.$,
|
|
'icon': 'align-float-right',
|
|
'label': ve.msg( 'visualeditor-dialog-media-position-right' )
|
|
} ),
|
|
], 0 );
|
|
|
|
this.positionCheckbox = new OO.ui.CheckboxInputWidget( {
|
|
'$': this.$
|
|
} );
|
|
positionField = new OO.ui.FieldLayout( this.positionCheckbox, {
|
|
'$': this.$,
|
|
'align': 'inline',
|
|
'label': ve.msg( 'visualeditor-dialog-media-position-checkbox' )
|
|
} );
|
|
|
|
positionFieldset = new OO.ui.FieldsetLayout( {
|
|
'$': this.$,
|
|
'label': ve.msg( 'visualeditor-dialog-media-position-section' ),
|
|
'icon': 'parameter'
|
|
} );
|
|
|
|
// Build position fieldset
|
|
positionFieldset.$element.append( [
|
|
positionField.$element,
|
|
this.positionInput.$element
|
|
] );
|
|
|
|
// Type
|
|
this.typeFieldset = new OO.ui.FieldsetLayout( {
|
|
'$': this.$,
|
|
'label': ve.msg( 'visualeditor-dialog-media-type-section' ),
|
|
'icon': 'parameter'
|
|
} );
|
|
|
|
this.typeInput = new OO.ui.ButtonSelectWidget( {
|
|
'$': this.$
|
|
} );
|
|
this.typeInput.addItems( [
|
|
// TODO: Inline images require a bit of further work, will be coming soon
|
|
new OO.ui.ButtonOptionWidget( 'thumb', {
|
|
'$': this.$,
|
|
'icon': 'image-thumbnail',
|
|
'label': ve.msg( 'visualeditor-dialog-media-type-thumb' )
|
|
} ),
|
|
new OO.ui.ButtonOptionWidget( 'frameless', {
|
|
'$': this.$,
|
|
'icon': 'image-frameless',
|
|
'label': ve.msg( 'visualeditor-dialog-media-type-frameless' )
|
|
} ),
|
|
new OO.ui.ButtonOptionWidget( 'frame', {
|
|
'$': this.$,
|
|
'icon': 'image-frame',
|
|
'label': ve.msg( 'visualeditor-dialog-media-type-frame' )
|
|
} ),
|
|
new OO.ui.ButtonOptionWidget( 'none', {
|
|
'$': this.$,
|
|
'icon': 'image-none',
|
|
'label': ve.msg( 'visualeditor-dialog-media-type-none' )
|
|
} )
|
|
] );
|
|
this.borderCheckbox = new OO.ui.CheckboxInputWidget( {
|
|
'$': this.$
|
|
} );
|
|
borderField = new OO.ui.FieldLayout( this.borderCheckbox, {
|
|
'$': this.$,
|
|
'align': 'inline',
|
|
'label': ve.msg( 'visualeditor-dialog-media-type-border' )
|
|
} );
|
|
|
|
// Build type fieldset
|
|
this.typeFieldset.$element.append( [
|
|
this.typeInput.$element,
|
|
borderField.$element
|
|
] );
|
|
|
|
// Size
|
|
this.sizeFieldset = new OO.ui.FieldsetLayout( {
|
|
'$': this.$,
|
|
'label': ve.msg( 'visualeditor-dialog-media-size-section' ),
|
|
'icon': 'parameter'
|
|
} );
|
|
|
|
this.sizeErrorLabel = new OO.ui.LabelWidget( {
|
|
'$': this.$,
|
|
'label': ve.msg( 'visualeditor-dialog-media-size-originalsize-error' )
|
|
} );
|
|
|
|
this.sizeWidget = new ve.ui.MediaSizeWidget( {}, {
|
|
'$': this.$
|
|
} );
|
|
|
|
this.$sizeWidgetElements = this.$( '<div>' ).append( [
|
|
this.sizeWidget.$element,
|
|
this.sizeErrorLabel.$element
|
|
] );
|
|
this.sizeFieldset.$element.append( [
|
|
this.$spinner,
|
|
this.$sizeWidgetElements
|
|
] );
|
|
|
|
// Get wiki default thumbnail size
|
|
this.defaultThumbSize = mw.config.get( 'wgVisualEditorConfig' ).defaultUserOptions.defaultthumbsize;
|
|
|
|
// Events
|
|
this.positionCheckbox.connect( this, { 'change': 'onPositionCheckboxChange' } );
|
|
this.sizeWidget.connect( this, { 'change': 'onSizeWidgetChange' } );
|
|
this.typeInput.connect( this, { 'select': 'onTypeChange' } );
|
|
this.bookletLayout.connect( this, { 'set': 'onBookletLayoutSet' } );
|
|
|
|
// Initialization
|
|
this.generalSettingsPage.$element.append( [
|
|
this.captionFieldset.$element,
|
|
altTextFieldset.$element
|
|
] );
|
|
|
|
this.advancedSettingsPage.$element.append( [
|
|
positionFieldset.$element,
|
|
this.typeFieldset.$element,
|
|
this.sizeFieldset.$element
|
|
] );
|
|
|
|
this.panels.addItems( [ this.bookletLayout ] );
|
|
};
|
|
|
|
/**
|
|
* Handle change event on the sizeWidget. Switch the size select
|
|
* from default to custom and vise versa based on the values in
|
|
* the widget.
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.onSizeWidgetChange = function () {
|
|
// Switch to 'default' or 'custom' size
|
|
if ( this.sizeWidget.isEmpty() ) {
|
|
this.sizeWidget.setSizeType( 'default' );
|
|
} else {
|
|
this.sizeWidget.setSizeType( 'custom' );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle type change, particularly to and from 'thumb' to make
|
|
* sure size is limited.
|
|
* @param {OO.ui.ButtonOptionWidget} item Selected item
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.onTypeChange = function ( item ) {
|
|
var selectedType = item ? item.getData() : '',
|
|
thumbOrFrameless = selectedType === 'thumb' || selectedType === 'frameless',
|
|
originalDimensions = this.scalable.getOriginalDimensions();
|
|
|
|
// As per wikitext docs, both 'thumb' and 'frameless' images are
|
|
// limited in max size to their original size
|
|
if ( thumbOrFrameless ) {
|
|
if ( originalDimensions ) {
|
|
// Set original dimensions as the max. In the future we may
|
|
// want to switch between original dimensions (in frameless
|
|
// and thumb) and perhaps some preset maximum dimensions for
|
|
// basic and frameless.
|
|
this.scalable.setMaxDimensions( originalDimensions );
|
|
this.scalable.setEnforcedMax( true );
|
|
} else {
|
|
// We don't have maximum dimensions available, so we can't
|
|
// enforce any max size
|
|
this.scalable.setEnforcedMax( false );
|
|
}
|
|
} else {
|
|
// Don't limit maximum dimensions on basic and frameless images
|
|
this.scalable.setEnforcedMax( false );
|
|
}
|
|
|
|
// Disable border checkbox for thumb and framed images
|
|
// According to documentation:
|
|
// https://en.wikipedia.org/wiki/Wikipedia:Extended_image_syntax#Border
|
|
if ( selectedType === 'thumb' || selectedType === 'frame' ) {
|
|
// Disable border option
|
|
this.borderCheckbox.setDisabled( true );
|
|
this.borderCheckbox.setValue( false );
|
|
} else {
|
|
// Enable border option
|
|
this.borderCheckbox.setDisabled( false );
|
|
}
|
|
|
|
// Re-validate the existing dimensions
|
|
this.sizeWidget.validateDimensions();
|
|
};
|
|
|
|
/**
|
|
* Handle change event on the positionCheckbox element. If an option
|
|
* is selected, mark the checkbox
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.onPositionCheckboxChange = function () {
|
|
var checked = this.positionCheckbox.getValue();
|
|
|
|
if ( !checked ) {
|
|
// If unchecked, remove selection
|
|
this.positionInput.selectItem( null );
|
|
} else {
|
|
// If checked, choose default position
|
|
if ( this.getFragment().getDocument().getDir() === 'ltr' ) {
|
|
// Assume default is 'right'
|
|
this.positionInput.selectItem(
|
|
this.positionInput.getItemFromData( 'right' )
|
|
);
|
|
} else {
|
|
// Assume default is 'left'
|
|
this.positionInput.selectItem(
|
|
this.positionInput.getItemFromData( 'left' )
|
|
);
|
|
}
|
|
}
|
|
|
|
this.positionInput.setDisabled( !checked );
|
|
};
|
|
|
|
ve.ui.MWMediaEditDialog.prototype.onBookletLayoutSet = function ( page ) {
|
|
// When switching to the general settings page, focus the surface
|
|
if ( page === this.generalSettingsPage ) {
|
|
this.captionSurface.focus();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.setup = function ( data ) {
|
|
var newDoc,
|
|
dialog = this,
|
|
doc = this.getFragment().getSurface().getDocument();
|
|
|
|
// Parent method
|
|
ve.ui.MWMediaEditDialog.super.prototype.setup.call( this, data );
|
|
|
|
// Properties
|
|
this.captionNode = this.selectedNode.getCaptionNode();
|
|
this.store = doc.getStore();
|
|
|
|
if ( this.captionNode && this.captionNode.getLength() > 0 ) {
|
|
newDoc = doc.cloneFromRange( this.captionNode.getRange() );
|
|
} else {
|
|
newDoc = new ve.dm.Document( [
|
|
{ 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } },
|
|
{ 'type': '/paragraph' },
|
|
{ 'type': 'internalList' },
|
|
{ 'type': '/internalList' }
|
|
] );
|
|
}
|
|
|
|
this.captionSurface = new ve.ui.SurfaceWidget(
|
|
newDoc,
|
|
{
|
|
'$': this.$,
|
|
'tools': this.constructor.static.toolbarGroups,
|
|
'commands': this.constructor.static.surfaceCommands,
|
|
'pasteRules': this.constructor.static.pasteRules
|
|
}
|
|
);
|
|
|
|
this.$spinner.show();
|
|
this.$sizeWidgetElements.hide();
|
|
this.sizeErrorLabel.$element.hide();
|
|
// Ask for the asynchronous call to get a full scalable object
|
|
// with original dimensions and imageinfo from the API
|
|
this.selectedNode.getScalablePromise()
|
|
.done( ve.bind( function () {
|
|
this.scalable = this.selectedNode.getScalable();
|
|
this.$spinner.hide();
|
|
this.$sizeWidgetElements.show();
|
|
|
|
if (
|
|
this.selectedNode.getAttribute( 'type' ) === 'thumb' &&
|
|
this.scalable.getOriginalDimensions()
|
|
) {
|
|
// Set the max dimensions to the image's original dimensions
|
|
this.scalable.setMaxDimensions(
|
|
this.scalable.getOriginalDimensions()
|
|
);
|
|
// Tell the size widget to limit maxDimensions to image's original dimensions
|
|
this.scalable.setEnforcedMax( true );
|
|
} else {
|
|
this.scalable.setEnforcedMax( false );
|
|
}
|
|
|
|
// Send the scalable object to the size widget
|
|
this.sizeWidget.setScalable( this.scalable );
|
|
this.scalable.setDefaultDimensions(
|
|
this.scalable.getDimensionsFromValue( { 'width': this.defaultThumbSize } )
|
|
);
|
|
}, this ) )
|
|
.fail( ve.bind( function () {
|
|
dialog.sizeErrorLabel.$element.show();
|
|
}, this ) );
|
|
|
|
// Initialize size
|
|
this.sizeWidget.setSizeType(
|
|
this.selectedNode.getAttribute( 'defaultSize' ) ?
|
|
'default' :
|
|
'custom'
|
|
);
|
|
|
|
// Set initial alt text
|
|
this.altTextInput.setValue( this.selectedNode.getAttribute( 'alt' ) || '' );
|
|
|
|
// Set initial position
|
|
if (
|
|
!this.selectedNode.getAttribute( 'align' ) ||
|
|
this.selectedNode.getAttribute( 'align' ) === 'none'
|
|
) {
|
|
this.positionCheckbox.setValue( false );
|
|
this.positionInput.setDisabled( true );
|
|
this.positionInput.selectItem( null );
|
|
} else {
|
|
this.positionCheckbox.setValue( true );
|
|
this.positionInput.setDisabled( false );
|
|
if ( this.selectedNode.getAttribute( 'align' ) === 'default' ) {
|
|
// Assume wiki default according to wiki dir
|
|
if ( this.getFragment().getDocument().getDir() === 'ltr' ) {
|
|
// Assume default is 'right'
|
|
this.positionInput.selectItem(
|
|
this.positionInput.getItemFromData( 'right' )
|
|
);
|
|
} else {
|
|
// Assume default is 'left'
|
|
this.positionInput.selectItem(
|
|
this.positionInput.getItemFromData( 'left' )
|
|
);
|
|
}
|
|
} else {
|
|
this.positionInput.selectItem(
|
|
this.positionInput.getItemFromData( this.selectedNode.getAttribute( 'align' ) )
|
|
);
|
|
}
|
|
}
|
|
|
|
// Border flag
|
|
this.borderCheckbox.setValue( !!this.selectedNode.getAttribute( 'borderImage' ) );
|
|
|
|
// Set image type
|
|
this.typeInput.selectItem( null );
|
|
if ( this.selectedNode.getAttribute( 'type' ) !== undefined ) {
|
|
this.typeInput.selectItem(
|
|
this.typeInput.getItemFromData( this.selectedNode.getAttribute( 'type' ) )
|
|
);
|
|
} else {
|
|
// Explicitly show 'none' if no type was specified
|
|
this.typeInput.selectItem(
|
|
this.typeInput.getItemFromData( 'none' )
|
|
);
|
|
}
|
|
|
|
// Initialization
|
|
this.captionFieldset.$element.append( this.captionSurface.$element );
|
|
this.captionSurface.initialize();
|
|
};
|
|
|
|
/**
|
|
* Handle window ready events
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.onReady = function () {
|
|
// Focus the caption surface
|
|
this.captionSurface.focus();
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.teardown = function ( data ) {
|
|
// Cleanup
|
|
this.captionSurface.destroy();
|
|
this.captionSurface = null;
|
|
this.captionNode = null;
|
|
|
|
// Parent method
|
|
ve.ui.MWMediaEditDialog.super.prototype.teardown.call( this, data );
|
|
};
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ve.ui.MWMediaEditDialog.prototype.applyChanges = function () {
|
|
var newDoc, doc, originalAlt, attr, transactionAttributes = {},
|
|
imageSizeType, imageType, imageAlignmentCheckbox,
|
|
imageAlignmentValue, originalDimensions,
|
|
fragment = this.getFragment(),
|
|
surfaceModel = fragment.getSurface();
|
|
|
|
newDoc = this.captionSurface.getSurface().getModel().getDocument();
|
|
doc = surfaceModel.getDocument();
|
|
if ( !this.captionNode ) {
|
|
// Insert a new caption at the beginning of the image node
|
|
fragment
|
|
.adjustRange( 1 )
|
|
.collapseRangeToStart()
|
|
.insertContent( [ { 'type': 'mwImageCaption' }, { 'type': '/mwImageCaption' } ] );
|
|
this.captionNode = this.selectedNode.getCaptionNode();
|
|
}
|
|
// Replace the contents of the caption
|
|
surfaceModel.change(
|
|
ve.dm.Transaction.newFromRemoval( doc, this.captionNode.getRange(), true )
|
|
);
|
|
surfaceModel.change(
|
|
ve.dm.Transaction.newFromDocumentInsertion( doc, this.captionNode.getRange().start, newDoc )
|
|
);
|
|
|
|
// Get all the details and their fallbacks
|
|
imageSizeType = this.sizeWidget.getSizeType() || 'default';
|
|
imageType = this.typeInput.getSelectedItem() ? this.typeInput.getSelectedItem().getData() : '';
|
|
imageAlignmentCheckbox = this.positionCheckbox.getValue();
|
|
if ( imageAlignmentCheckbox && this.positionInput.getSelectedItem() ) {
|
|
imageAlignmentValue = this.positionInput.getSelectedItem().getData();
|
|
}
|
|
|
|
// Size and scalabletravaganza
|
|
attr = null;
|
|
if ( imageSizeType === 'default' ) {
|
|
transactionAttributes.defaultSize = true;
|
|
originalDimensions = this.scalable.getOriginalDimensions();
|
|
// Figure out the default size
|
|
if ( imageType === 'thumb' || imageType === 'frame' ) {
|
|
// Default is thumb-default unless the image is originally smaller
|
|
if ( originalDimensions.width > this.defaultThumbSize ) {
|
|
attr = this.scalable.getDimensionsFromValue( { 'width': this.defaultThumbSize } );
|
|
} else {
|
|
attr = originalDimensions;
|
|
}
|
|
} else {
|
|
// Default is full size
|
|
if ( originalDimensions ) {
|
|
attr = originalDimensions;
|
|
}
|
|
}
|
|
|
|
// Apply
|
|
if ( attr ) {
|
|
transactionAttributes.width = attr.width;
|
|
transactionAttributes.height = attr.height;
|
|
}
|
|
// Upright is not yet implemented in Parsoid. When it is,
|
|
// the scale properties should be implemented here
|
|
//} else if ( imageSizeType === 'scale' ) {
|
|
} else if ( imageSizeType === 'custom' && this.sizeWidget.isValid() ) {
|
|
attr = this.sizeWidget.getCurrentDimensions();
|
|
transactionAttributes.width = attr.width;
|
|
transactionAttributes.height = attr.height;
|
|
transactionAttributes.defaultSize = false;
|
|
}
|
|
|
|
// Set alternate text
|
|
attr = $.trim( this.altTextInput.getValue() );
|
|
originalAlt = this.selectedNode.getAttribute( 'alt' );
|
|
// Allow the user to submit an empty alternate text but
|
|
// not if there was no alternate text originally to avoid
|
|
// dirty diffing images with empty |alt=
|
|
if (
|
|
// If there was no original alternate text but there
|
|
// is a value now, update
|
|
( originalAlt === undefined && attr ) ||
|
|
// If original alternate text was defined, always
|
|
// update, even if the input is empty to allow the
|
|
// user to unset it
|
|
originalAlt !== undefined
|
|
) {
|
|
transactionAttributes.alt = attr;
|
|
}
|
|
|
|
if ( !imageAlignmentCheckbox ) {
|
|
// Only change to 'none' if alignment was originally
|
|
// set to anything else
|
|
if (
|
|
this.selectedNode.getAttribute( 'align' ) &&
|
|
this.selectedNode.getAttribute( 'align' ) !== 'none'
|
|
) {
|
|
transactionAttributes.align = 'none';
|
|
}
|
|
} else {
|
|
// If alignment was originally default and is still
|
|
// set to the default position according to the wiki
|
|
// content direction, do not change it
|
|
if (
|
|
(
|
|
this.selectedNode.getAttribute( 'align' ) === 'default' &&
|
|
(
|
|
this.getFragment().getDocument().getDir() === 'ltr' &&
|
|
imageAlignmentValue !== 'right'
|
|
) ||
|
|
(
|
|
this.getFragment().getDocument().getDir() === 'rtl' &&
|
|
imageAlignmentValue !== 'left'
|
|
)
|
|
) ||
|
|
this.selectedNode.getAttribute( 'align' ) !== 'default'
|
|
) {
|
|
transactionAttributes.align = imageAlignmentValue;
|
|
}
|
|
}
|
|
|
|
// Border
|
|
if (
|
|
!this.borderCheckbox.isDisabled() &&
|
|
this.borderCheckbox.getValue() === true
|
|
) {
|
|
transactionAttributes.borderImage = true;
|
|
} else {
|
|
transactionAttributes.borderImage = false;
|
|
}
|
|
|
|
// Image type
|
|
if ( imageType ) {
|
|
transactionAttributes.type = imageType;
|
|
}
|
|
surfaceModel.change(
|
|
ve.dm.Transaction.newFromAttributeChanges(
|
|
doc, this.selectedNode.getOffset(), transactionAttributes
|
|
)
|
|
);
|
|
|
|
// Parent method
|
|
return ve.ui.MWMediaEditDialog.super.prototype.applyChanges.call( this );
|
|
};
|
|
|
|
/* Registration */
|
|
|
|
ve.ui.windowFactory.register( ve.ui.MWMediaEditDialog );
|