2016-03-08 21:14:12 +00:00
|
|
|
/*!
|
|
|
|
* VisualEditor user interface MWGalleryDialog class.
|
|
|
|
*
|
|
|
|
* @copyright 2016 VisualEditor Team and others; see AUTHORS.txt
|
|
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dialog for editing MediaWiki galleries.
|
|
|
|
*
|
|
|
|
* @class
|
|
|
|
* @extends ve.ui.MWExtensionDialog
|
|
|
|
*
|
|
|
|
* @constructor
|
|
|
|
* @param {Object} [config] Configuration options
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog = function VeUiMWGalleryDialog() {
|
|
|
|
// Parent constructor
|
|
|
|
ve.ui.MWGalleryDialog.super.apply( this, arguments );
|
|
|
|
|
|
|
|
this.$element.addClass( 've-ui-mwGalleryDialog' );
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Inheritance */
|
|
|
|
|
|
|
|
OO.inheritClass( ve.ui.MWGalleryDialog, ve.ui.MWExtensionDialog );
|
|
|
|
|
|
|
|
/* Static properties */
|
|
|
|
|
|
|
|
ve.ui.MWGalleryDialog.static.name = 'gallery';
|
|
|
|
|
|
|
|
ve.ui.MWGalleryDialog.static.size = 'large';
|
|
|
|
|
|
|
|
ve.ui.MWGalleryDialog.static.title =
|
|
|
|
OO.ui.deferMsg( 'visualeditor-mwgallerydialog-title' );
|
|
|
|
|
|
|
|
ve.ui.MWGalleryDialog.static.modelClasses = [ ve.dm.MWGalleryNode ];
|
|
|
|
|
|
|
|
/* Methods */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.initialize = function () {
|
2016-11-30 21:48:37 +00:00
|
|
|
var imagesCard, optionsCard, menuLayout,
|
|
|
|
innerMenuLayout, innerMenuPanel, innerContentPanel,
|
2016-03-08 21:14:12 +00:00
|
|
|
modeField, captionField, widthsField, heightsField,
|
|
|
|
perrowField, showFilenameField, classesField, stylesField;
|
|
|
|
|
|
|
|
// Parent method
|
|
|
|
ve.ui.MWGalleryDialog.super.prototype.initialize.call( this );
|
|
|
|
|
|
|
|
// States
|
|
|
|
this.highlightedItem = null;
|
|
|
|
this.searchPanelVisible = false;
|
2016-11-19 15:51:21 +00:00
|
|
|
this.selectedFilenames = {};
|
|
|
|
this.initialImageData = [];
|
2016-03-08 21:14:12 +00:00
|
|
|
|
2016-08-04 23:28:53 +00:00
|
|
|
// Default settings
|
|
|
|
this.defaults = mw.config.get( 'wgVisualEditorConfig' ).galleryOptions;
|
|
|
|
|
2016-03-08 21:14:12 +00:00
|
|
|
// Images and options cards
|
2016-10-12 05:07:37 +00:00
|
|
|
this.indexLayout = new OO.ui.IndexLayout( {
|
2016-03-08 21:14:12 +00:00
|
|
|
scrollable: false,
|
|
|
|
expanded: true
|
|
|
|
} );
|
|
|
|
imagesCard = new OO.ui.CardLayout( 'images', {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-card-images' ),
|
|
|
|
expandable: false,
|
|
|
|
scrollable: false,
|
|
|
|
padded: true
|
|
|
|
} );
|
|
|
|
optionsCard = new OO.ui.CardLayout( 'options', {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-card-options' ),
|
|
|
|
expandable: false,
|
|
|
|
scrollable: false,
|
|
|
|
padded: true
|
|
|
|
} );
|
|
|
|
|
|
|
|
// Images card
|
|
|
|
|
|
|
|
// General layout
|
2016-11-30 21:48:37 +00:00
|
|
|
menuLayout = new OO.ui.MenuLayout( {
|
|
|
|
classes: [ 've-ui-mwGalleryDialog-menuLayout' ]
|
|
|
|
} );
|
|
|
|
innerMenuLayout = new OO.ui.MenuLayout( {
|
|
|
|
menuPosition: 'bottom',
|
|
|
|
classes: [ 've-ui-mwGalleryDialog-innerMenuLayout' ]
|
|
|
|
} );
|
|
|
|
innerMenuPanel = new OO.ui.PanelLayout( {
|
2016-03-08 21:14:12 +00:00
|
|
|
padded: true,
|
|
|
|
expanded: true,
|
|
|
|
scrollable: true
|
|
|
|
} );
|
2016-11-30 21:48:37 +00:00
|
|
|
innerContentPanel = new OO.ui.PanelLayout( {
|
|
|
|
padded: true,
|
|
|
|
expanded: true
|
|
|
|
} );
|
2016-03-08 21:14:12 +00:00
|
|
|
this.editPanel = new OO.ui.PanelLayout( {
|
|
|
|
padded: true,
|
|
|
|
expanded: true,
|
|
|
|
scrollable: true
|
|
|
|
} );
|
|
|
|
this.searchPanel = new OO.ui.PanelLayout( {
|
|
|
|
padded: true,
|
|
|
|
expanded: true,
|
|
|
|
scrollable: true
|
|
|
|
} ).toggle( false );
|
|
|
|
|
|
|
|
// Menu
|
|
|
|
this.$emptyGalleryMessage = $( '<div>' )
|
|
|
|
.addClass( 'oo-ui-element-hidden' )
|
|
|
|
.text( ve.msg( 'visualeditor-mwgallerydialog-empty-gallery-message' ) );
|
|
|
|
this.galleryGroup = new ve.ui.MWGalleryGroupWidget();
|
|
|
|
this.showSearchPanelButton = new OO.ui.ButtonWidget( {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-search-button-label' ),
|
|
|
|
flags: [ 'progressive' ],
|
|
|
|
classes: [ 've-ui-mwGalleryDialog-show-search-panel-button' ]
|
|
|
|
} );
|
|
|
|
|
|
|
|
// Edit panel
|
|
|
|
this.$highlightedImage = $( '<div>' )
|
|
|
|
.addClass( 've-ui-mwGalleryDialog-highlighted-image' );
|
|
|
|
// TODO: make into a ve.ui.MWTargetWidget once Parsoid handles galleries
|
|
|
|
this.highlightedCaptionInput = new OO.ui.TextInputWidget( {
|
2016-11-24 00:09:49 +00:00
|
|
|
placeholder: ve.msg( 'visualeditor-mwgallerydialog-image-caption-placeholder' ),
|
2016-07-06 16:24:12 +00:00
|
|
|
multiline: true,
|
|
|
|
autosize: true
|
2016-03-08 21:14:12 +00:00
|
|
|
} );
|
|
|
|
this.removeButton = new OO.ui.ButtonWidget( {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-remove-button-label' ),
|
|
|
|
flags: [ 'destructive' ],
|
|
|
|
classes: [ 've-ui-mwGalleryDialog-remove-button' ]
|
|
|
|
} );
|
|
|
|
|
|
|
|
// Search panel
|
2016-12-03 16:31:23 +00:00
|
|
|
this.searchWidget = new mw.widgets.MediaSearchWidget( {
|
|
|
|
rowHeight: 150
|
|
|
|
} );
|
2016-03-08 21:14:12 +00:00
|
|
|
|
|
|
|
// Options card
|
|
|
|
|
|
|
|
// Input widgets
|
|
|
|
this.modeDropdown = new OO.ui.DropdownWidget( {
|
|
|
|
menu: {
|
|
|
|
items: [
|
|
|
|
new OO.ui.OptionWidget( {
|
|
|
|
data: 'traditional',
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-mode-dropdown-label-traditional' )
|
|
|
|
} ),
|
|
|
|
new OO.ui.OptionWidget( {
|
|
|
|
data: 'nolines',
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-mode-dropdown-label-nolines' )
|
|
|
|
} ),
|
|
|
|
new OO.ui.OptionWidget( {
|
|
|
|
data: 'packed',
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-mode-dropdown-label-packed' )
|
|
|
|
} ),
|
|
|
|
new OO.ui.OptionWidget( {
|
|
|
|
data: 'packed-overlay',
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-mode-dropdown-label-packed-overlay' )
|
|
|
|
} ),
|
|
|
|
new OO.ui.OptionWidget( {
|
|
|
|
data: 'packed-hover',
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-mode-dropdown-label-packed-hover' )
|
2016-07-07 17:45:44 +00:00
|
|
|
} ),
|
|
|
|
new OO.ui.OptionWidget( {
|
|
|
|
data: 'slideshow',
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-mode-dropdown-label-slideshow' )
|
2016-03-08 21:14:12 +00:00
|
|
|
} )
|
|
|
|
]
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
this.captionInput = new OO.ui.TextInputWidget( {
|
|
|
|
placeholder: ve.msg( 'visualeditor-mwgallerydialog-caption-input-placeholder' )
|
|
|
|
} );
|
|
|
|
this.widthsInput = new OO.ui.NumberInputWidget( {
|
|
|
|
min: 0,
|
2016-08-04 23:28:53 +00:00
|
|
|
showButtons: false,
|
|
|
|
input: {
|
|
|
|
placeholder: ve.msg( 'visualeditor-mwgallerydialog-widths-input-placeholder', this.defaults.imageWidth )
|
|
|
|
}
|
2016-03-08 21:14:12 +00:00
|
|
|
} );
|
|
|
|
this.heightsInput = new OO.ui.NumberInputWidget( {
|
|
|
|
min: 0,
|
2016-08-04 23:28:53 +00:00
|
|
|
showButtons: false,
|
|
|
|
input: {
|
|
|
|
placeholder: ve.msg( 'visualeditor-mwgallerydialog-heights-input-placeholder', this.defaults.imageHeight )
|
|
|
|
}
|
2016-03-08 21:14:12 +00:00
|
|
|
} );
|
|
|
|
this.perrowInput = new OO.ui.NumberInputWidget( {
|
|
|
|
min: 0,
|
|
|
|
showButtons: false
|
|
|
|
} );
|
|
|
|
this.showFilenameCheckbox = new OO.ui.CheckboxInputWidget( {
|
|
|
|
value: 'yes'
|
|
|
|
} );
|
|
|
|
this.classesInput = new OO.ui.TextInputWidget( {
|
|
|
|
placeholder: ve.msg( 'visualeditor-mwgallerydialog-classes-input-placeholder' )
|
|
|
|
} );
|
|
|
|
this.stylesInput = new OO.ui.TextInputWidget( {
|
|
|
|
placeholder: ve.msg( 'visualeditor-mwgallerydialog-styles-input-placeholder' )
|
|
|
|
} );
|
|
|
|
|
|
|
|
// Field layouts
|
|
|
|
modeField = new OO.ui.FieldLayout( this.modeDropdown, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-mode-field-label' )
|
|
|
|
} );
|
|
|
|
captionField = new OO.ui.FieldLayout( this.captionInput, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-caption-field-label' )
|
|
|
|
} );
|
|
|
|
widthsField = new OO.ui.FieldLayout( this.widthsInput, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-widths-field-label' )
|
|
|
|
} );
|
|
|
|
heightsField = new OO.ui.FieldLayout( this.heightsInput, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-heights-field-label' )
|
|
|
|
} );
|
|
|
|
perrowField = new OO.ui.FieldLayout( this.perrowInput, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-perrow-field-label' )
|
|
|
|
} );
|
|
|
|
showFilenameField = new OO.ui.FieldLayout( this.showFilenameCheckbox, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-show-filename-field-label' )
|
|
|
|
} );
|
|
|
|
classesField = new OO.ui.FieldLayout( this.classesInput, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-classes-field-label' )
|
|
|
|
} );
|
|
|
|
stylesField = new OO.ui.FieldLayout( this.stylesInput, {
|
|
|
|
label: ve.msg( 'visualeditor-mwgallerydialog-styles-field-label' )
|
|
|
|
} );
|
|
|
|
|
|
|
|
// Append everything
|
2016-11-30 21:48:37 +00:00
|
|
|
innerMenuLayout.$menu.append(
|
|
|
|
innerContentPanel.$element.append(
|
2016-03-08 21:14:12 +00:00
|
|
|
this.showSearchPanelButton.$element
|
|
|
|
)
|
|
|
|
);
|
2016-11-30 21:48:37 +00:00
|
|
|
innerMenuLayout.$content.append(
|
|
|
|
innerMenuPanel.$element.append(
|
|
|
|
this.$emptyGalleryMessage,
|
|
|
|
this.galleryGroup.$element
|
|
|
|
)
|
|
|
|
);
|
|
|
|
menuLayout.$menu.append(
|
|
|
|
innerMenuLayout.$element
|
|
|
|
);
|
2016-03-08 21:14:12 +00:00
|
|
|
menuLayout.$content.append(
|
|
|
|
this.editPanel.$element.append(
|
|
|
|
this.$highlightedImage,
|
|
|
|
this.highlightedCaptionInput.$element,
|
|
|
|
this.removeButton.$element
|
|
|
|
),
|
|
|
|
this.searchPanel.$element.append(
|
|
|
|
this.searchWidget.$element
|
|
|
|
)
|
|
|
|
);
|
|
|
|
imagesCard.$element.append(
|
|
|
|
menuLayout.$element
|
|
|
|
);
|
|
|
|
optionsCard.$element.append(
|
|
|
|
modeField.$element,
|
|
|
|
captionField.$element,
|
|
|
|
widthsField.$element,
|
|
|
|
heightsField.$element,
|
|
|
|
perrowField.$element,
|
|
|
|
showFilenameField.$element,
|
|
|
|
classesField.$element,
|
|
|
|
stylesField.$element
|
|
|
|
);
|
2016-10-12 05:07:37 +00:00
|
|
|
this.indexLayout.addCards( [
|
2016-03-08 21:14:12 +00:00
|
|
|
imagesCard,
|
|
|
|
optionsCard
|
|
|
|
] );
|
2016-10-12 05:07:37 +00:00
|
|
|
this.$body.append( this.indexLayout.$element );
|
2016-03-08 21:14:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.getSetupProcess = function ( data ) {
|
|
|
|
return ve.ui.MWGalleryDialog.super.prototype.getSetupProcess.call( this, data )
|
|
|
|
.next( function () {
|
|
|
|
var titlesString, title, titleText, imageTitles, mode,
|
|
|
|
caption, widths, heights, perrow,
|
|
|
|
showFilename, classes, styles,
|
2016-11-29 16:19:06 +00:00
|
|
|
namespaceIds = mw.config.get( 'wgNamespaceIds' ),
|
2016-03-08 21:14:12 +00:00
|
|
|
dialog = this,
|
|
|
|
attributes = this.selectedNode && this.selectedNode.getAttribute( 'mw' ).attrs;
|
|
|
|
|
|
|
|
// Images card
|
|
|
|
// If editing an existing gallery, populate with the images...
|
|
|
|
if ( this.selectedNode ) {
|
|
|
|
imageTitles = [];
|
|
|
|
|
|
|
|
// Get image and caption data
|
|
|
|
// TODO: Can be multiple pipes. See parser.php -> renderImageGallery in MediaWiki
|
|
|
|
$.trim( this.selectedNode.getAttribute( 'mw' ).body.extsrc )
|
|
|
|
.split( '\n' ).forEach( function ( line ) {
|
|
|
|
var matches;
|
|
|
|
|
|
|
|
// Match lines like:
|
|
|
|
// Image:someimage.jpg|This is some image
|
|
|
|
matches = line.match( /^([^|]+)(\|(.*))?$/ );
|
|
|
|
|
|
|
|
// Ignore any empty lines
|
|
|
|
if ( matches ) {
|
2016-11-23 00:02:59 +00:00
|
|
|
// The "File:" prefix is optional in wikitext galleries. This will add
|
|
|
|
// the prefix if there is no prefix, but won't change an existing
|
|
|
|
// prefix (e.g. "Category:")
|
|
|
|
title = mw.Title.newFromText( matches[ 1 ], namespaceIds.file );
|
2016-03-08 21:14:12 +00:00
|
|
|
// Ignore any invalid titles
|
|
|
|
// (which will result in title being null)
|
|
|
|
if ( title ) {
|
|
|
|
titleText = title.getPrefixedText();
|
|
|
|
imageTitles.push( titleText );
|
2016-11-19 15:51:21 +00:00
|
|
|
dialog.initialImageData.push( {
|
|
|
|
title: titleText,
|
2016-11-28 17:36:29 +00:00
|
|
|
caption: matches[ 3 ] || ''
|
2016-11-19 15:51:21 +00:00
|
|
|
} );
|
2016-03-08 21:14:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Populate menu and edit panels
|
|
|
|
titlesString = imageTitles.join( '|' );
|
|
|
|
this.imagesPromise = this.requestImages( {
|
|
|
|
titlesString: titlesString
|
|
|
|
} ).done( function () {
|
|
|
|
dialog.onHighlightItem();
|
|
|
|
} );
|
|
|
|
|
|
|
|
// ...Otherwise show the search panel
|
|
|
|
} else {
|
|
|
|
this.toggleEmptyGalleryMessage( true );
|
|
|
|
this.showSearchPanelButton.toggle( false );
|
|
|
|
this.toggleSearchPanel( true );
|
|
|
|
this.updateActions();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Options card
|
|
|
|
|
|
|
|
// Set options
|
2016-08-04 23:28:53 +00:00
|
|
|
mode = attributes && attributes.mode || this.defaults.mode;
|
2016-03-08 21:14:12 +00:00
|
|
|
caption = attributes && attributes.caption || '';
|
|
|
|
widths = attributes && parseInt( attributes.widths ) || '';
|
|
|
|
heights = attributes && parseInt( attributes.heights ) || '';
|
|
|
|
perrow = attributes && attributes.perrow || '';
|
|
|
|
showFilename = attributes && attributes.showfilename === 'yes';
|
|
|
|
classes = attributes && attributes.class || '';
|
|
|
|
styles = attributes && attributes.style || '';
|
|
|
|
|
|
|
|
// Populate options panel
|
|
|
|
this.modeDropdown.getMenu().selectItemByData( mode );
|
|
|
|
this.captionInput.setValue( caption );
|
|
|
|
this.widthsInput.setValue( widths );
|
|
|
|
this.heightsInput.setValue( heights );
|
|
|
|
this.perrowInput.setValue( perrow );
|
|
|
|
this.showFilenameCheckbox.setSelected( showFilename );
|
|
|
|
this.classesInput.setValue( classes );
|
|
|
|
this.stylesInput.setValue( styles );
|
|
|
|
|
|
|
|
// Add event handlers
|
2016-10-12 05:07:37 +00:00
|
|
|
this.indexLayout.connect( this, { set: 'updateDialogSize' } );
|
2016-03-08 21:14:12 +00:00
|
|
|
this.searchWidget.getResults().connect( this, { choose: 'onSearchResultsChoose' } );
|
|
|
|
this.showSearchPanelButton.connect( this, { click: 'onShowSearchPanelButtonClick' } );
|
|
|
|
this.galleryGroup.connect( this, { editItem: 'onHighlightItem' } );
|
|
|
|
this.removeButton.connect( this, { click: 'onRemoveItem' } );
|
|
|
|
this.modeDropdown.getMenu().connect( this, { choose: 'onModeDropdownChange' } );
|
|
|
|
|
|
|
|
// Hack: Give the input a value so that this.insertOrUpdateNode gets called
|
|
|
|
this.input.setValue( 'gallery' );
|
|
|
|
}, this );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.getReadyProcess = function ( data ) {
|
|
|
|
return ve.ui.MWGalleryDialog.super.prototype.getReadyProcess.call( this, data )
|
|
|
|
.next( function () {
|
2016-09-27 20:50:15 +00:00
|
|
|
this.searchWidget.getQuery().focus().select();
|
2016-03-08 21:14:12 +00:00
|
|
|
return this.imagesPromise;
|
|
|
|
}, this );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.getTeardownProcess = function ( data ) {
|
|
|
|
return ve.ui.MWGalleryDialog.super.prototype.getTeardownProcess.call( this, data )
|
|
|
|
.first( function () {
|
|
|
|
this.galleryGroup.clearItems();
|
|
|
|
this.highlightedItem = null;
|
|
|
|
this.searchWidget.getQuery().setValue( '' );
|
|
|
|
this.searchWidget.teardown();
|
|
|
|
this.searchPanelVisible = false;
|
|
|
|
|
|
|
|
// Disconnect events
|
2016-10-12 05:07:37 +00:00
|
|
|
this.indexLayout.disconnect( this );
|
2016-03-08 21:14:12 +00:00
|
|
|
this.searchWidget.getResults().disconnect( this );
|
|
|
|
this.showSearchPanelButton.disconnect( this );
|
|
|
|
this.galleryGroup.disconnect( this );
|
|
|
|
this.removeButton.disconnect( this );
|
|
|
|
this.modeDropdown.disconnect( this );
|
|
|
|
}, this );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.getBodyHeight = function () {
|
|
|
|
return 600;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request the images for the images card menu
|
|
|
|
*
|
|
|
|
* @param {Object} options Options for the request
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.requestImages = function ( options ) {
|
|
|
|
return new mw.Api().get( {
|
|
|
|
action: 'query',
|
|
|
|
prop: 'imageinfo',
|
|
|
|
iiprop: 'url',
|
|
|
|
iiurlwidth: options.width || 200,
|
|
|
|
// Matches height of this.$highlightedImage
|
|
|
|
iiurlheight: options.height || 200,
|
|
|
|
titles: options.titlesString
|
|
|
|
} ).done( this.onRequestImagesSuccess.bind( this ) );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create items for the returned images and add them to the gallery group
|
|
|
|
*
|
|
|
|
* @param {Object} deferred jQuery deferred object
|
|
|
|
* @param {Object} response jQuery response object
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.onRequestImagesSuccess = function ( deferred, response ) {
|
2016-10-20 01:06:54 +00:00
|
|
|
var index, title,
|
2016-03-08 21:14:12 +00:00
|
|
|
thumbUrls = {},
|
|
|
|
items = [],
|
|
|
|
pages = response.responseJSON.query.pages;
|
|
|
|
|
|
|
|
// Store object of titles to thumbUrls
|
|
|
|
for ( index in pages ) {
|
|
|
|
if ( pages[ index ].imageinfo ) {
|
|
|
|
thumbUrls[ pages[ index ].title ] = pages[ index ].imageinfo[ 0 ].thumburl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-19 15:51:21 +00:00
|
|
|
if ( this.initialImageData.length > 0 ) {
|
|
|
|
this.initialImageData.forEach( function ( image ) {
|
|
|
|
image.thumbUrl = thumbUrls[ image.title ];
|
|
|
|
items.push( new ve.ui.MWGalleryItemWidget( image ) );
|
|
|
|
} );
|
|
|
|
this.initialImageData = [];
|
|
|
|
} else {
|
|
|
|
for ( title in this.selectedFilenames ) {
|
|
|
|
if ( Object.prototype.hasOwnProperty.call( thumbUrls, title ) ) {
|
|
|
|
items.push( new ve.ui.MWGalleryItemWidget( {
|
|
|
|
title: title,
|
|
|
|
thumbUrl: thumbUrls[ title ]
|
|
|
|
} ) );
|
|
|
|
delete this.selectedFilenames[ title ];
|
|
|
|
}
|
2016-10-20 01:06:54 +00:00
|
|
|
}
|
|
|
|
}
|
2016-03-08 21:14:12 +00:00
|
|
|
this.galleryGroup.addItems( items );
|
|
|
|
|
|
|
|
// Gallery is no longer empty
|
|
|
|
this.updateActions();
|
|
|
|
this.toggleEmptyGalleryMessage( false );
|
|
|
|
this.showSearchPanelButton.toggle( true );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request a new image and highlight it
|
|
|
|
*
|
|
|
|
* @param {string} title File name for the new image
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.addNewImage = function ( title ) {
|
|
|
|
var dialog = this;
|
|
|
|
|
2016-11-19 15:51:21 +00:00
|
|
|
// Make list of unique pending images, for onRequestImagesSuccess
|
|
|
|
this.selectedFilenames[ title ] = true;
|
2016-03-08 21:14:12 +00:00
|
|
|
|
|
|
|
// Request image
|
|
|
|
this.requestImages( {
|
|
|
|
titlesString: title
|
|
|
|
} ).done( function () {
|
|
|
|
|
|
|
|
// populate edit panel with the new image
|
|
|
|
var items = dialog.galleryGroup.items;
|
|
|
|
dialog.onHighlightItem( items[ items.length - 1 ] );
|
|
|
|
dialog.highlightedCaptionInput.focus();
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle search results choose event.
|
|
|
|
*
|
2016-11-16 18:21:22 +00:00
|
|
|
* @param {mw.widgets.MediaResultWidget} item Chosen item
|
2016-03-08 21:14:12 +00:00
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.onSearchResultsChoose = function ( item ) {
|
2016-11-14 22:04:25 +00:00
|
|
|
var title = mw.Title.newFromText( item.getData().title ).getPrefixedText();
|
|
|
|
|
2016-11-19 15:51:21 +00:00
|
|
|
if ( !Object.prototype.hasOwnProperty( this.selectedFilenames, title ) ) {
|
2016-10-20 01:06:54 +00:00
|
|
|
this.addNewImage( title );
|
|
|
|
}
|
2016-03-08 21:14:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle click event for the remove button
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.onRemoveItem = function () {
|
|
|
|
|
|
|
|
// Remove the highlighted item
|
|
|
|
this.galleryGroup.removeItems( [ this.highlightedItem ] );
|
|
|
|
|
|
|
|
// Show the search panel if the gallery is now empty...
|
|
|
|
if ( this.galleryGroup.items.length === 0 ) {
|
|
|
|
this.toggleEmptyGalleryMessage( true );
|
|
|
|
this.showSearchPanelButton.toggle( false );
|
|
|
|
this.toggleSearchPanel( true );
|
|
|
|
|
|
|
|
// ...Otherwise highlight the first item in the gallery
|
|
|
|
} else {
|
|
|
|
this.onHighlightItem();
|
|
|
|
}
|
|
|
|
this.updateActions();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle clicking on an image in the menu
|
|
|
|
*
|
|
|
|
* @param {ve.ui.MWGalleryItemWidget} item The item that was clicked on
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.onHighlightItem = function ( item ) {
|
|
|
|
// Unhighlight previous item
|
|
|
|
if ( this.highlightedItem ) {
|
|
|
|
this.highlightedItem.toggleHighlighted( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show edit panel
|
|
|
|
this.toggleSearchPanel( false );
|
|
|
|
|
|
|
|
// Highlight new item
|
2016-11-15 23:05:05 +00:00
|
|
|
item = item || this.galleryGroup.items[ 0 ];
|
2016-03-08 21:14:12 +00:00
|
|
|
item.toggleHighlighted( true );
|
|
|
|
this.highlightedItem = item;
|
|
|
|
|
|
|
|
// Populate edit panel
|
|
|
|
this.$highlightedImage
|
|
|
|
.css( 'background-image', 'url(' + item.thumbUrl + ')' );
|
|
|
|
this.highlightedCaptionInput
|
|
|
|
.setValue( item.caption );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle change event for this.modeDropdown
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.onModeDropdownChange = function () {
|
|
|
|
var mode = this.modeDropdown.getMenu().getSelectedItem().getData(),
|
2016-07-07 17:45:44 +00:00
|
|
|
disabled = (
|
|
|
|
mode === 'packed' ||
|
|
|
|
mode === 'packed-overlay' ||
|
|
|
|
mode === 'packed-hover' ||
|
|
|
|
mode === 'slideshow'
|
|
|
|
);
|
2016-03-08 21:14:12 +00:00
|
|
|
|
|
|
|
this.widthsInput.setDisabled( disabled );
|
|
|
|
this.perrowInput.setDisabled( disabled );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle click event for showSearchPanelButton
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.onShowSearchPanelButtonClick = function () {
|
|
|
|
this.toggleSearchPanel( true );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggle the search panel (and the edit panel, the opposite way)
|
|
|
|
*
|
|
|
|
* @param {boolean} visible The search panel is visible
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.toggleSearchPanel = function ( visible ) {
|
2016-11-29 16:19:06 +00:00
|
|
|
var pageTitle, namespace, namespacesWithSubpages;
|
|
|
|
|
2016-03-08 21:14:12 +00:00
|
|
|
visible = visible !== undefined ? visible : !this.searchPanelVisible;
|
|
|
|
|
|
|
|
// If currently visible panel is an edit panel, store the caption
|
|
|
|
if ( !this.searchPanelVisible && this.highlightedItem ) {
|
|
|
|
this.highlightedItem.setCaption(
|
|
|
|
this.highlightedCaptionInput.getValue()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Record the state of the search panel
|
|
|
|
this.searchPanelVisible = visible;
|
|
|
|
|
|
|
|
// Toggle the search panel, and do the opposite for the edit panel
|
|
|
|
this.searchPanel.toggle( visible );
|
|
|
|
this.editPanel.toggle( !visible );
|
|
|
|
|
|
|
|
// If the edit panel is visible, focus the caption input
|
|
|
|
if ( !visible ) {
|
|
|
|
this.highlightedCaptionInput.focus();
|
|
|
|
} else {
|
2016-11-29 16:19:06 +00:00
|
|
|
if ( !this.searchWidget.getQuery().getValue() ) {
|
|
|
|
// Wait until the search panel is visible before setting a default query
|
|
|
|
// as this triggers a request and render.
|
|
|
|
pageTitle = mw.config.get( 'wgTitle' );
|
|
|
|
namespace = mw.config.get( 'wgNamespaceNumber' );
|
|
|
|
namespacesWithSubpages = mw.config.get( 'wgVisualEditorConfig' ).namespacesWithSubpages;
|
|
|
|
|
|
|
|
if ( namespacesWithSubpages[ namespace ] ) {
|
|
|
|
pageTitle = pageTitle.slice( pageTitle.lastIndexOf( '/' ) + 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
this.searchWidget.getQuery().setValue( pageTitle );
|
|
|
|
}
|
|
|
|
|
2016-09-27 20:50:15 +00:00
|
|
|
this.searchWidget.getQuery().focus().select();
|
2016-03-08 21:14:12 +00:00
|
|
|
}
|
2016-10-12 05:07:37 +00:00
|
|
|
this.updateDialogSize();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resize the dialog according to which panel is focused
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.updateDialogSize = function () {
|
|
|
|
if ( this.searchPanelVisible && this.indexLayout.currentCardName === 'images' ) {
|
|
|
|
this.setSize( 'larger' );
|
|
|
|
} else {
|
|
|
|
this.setSize( 'large' );
|
|
|
|
}
|
2016-03-08 21:14:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggle the empty gallery message
|
|
|
|
*
|
|
|
|
* @param {boolean} empty The gallery is empty
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.toggleEmptyGalleryMessage = function ( empty ) {
|
|
|
|
if ( empty ) {
|
|
|
|
this.$emptyGalleryMessage.removeClass( 'oo-ui-element-hidden' );
|
|
|
|
} else {
|
|
|
|
this.$emptyGalleryMessage.addClass( 'oo-ui-element-hidden' );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disable the "Done" button if the gallery is empty, otherwise enable it
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.updateActions = function () {
|
|
|
|
this.actions.setAbilities( { done: this.galleryGroup.items.length > 0 } );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.ui.MWGalleryDialog.prototype.updateMwData = function ( mwData ) {
|
|
|
|
var i, ilen, mode, caption, widths, heights, perrow,
|
|
|
|
showFilename, classes, styles,
|
|
|
|
extsrc = '',
|
|
|
|
items = this.galleryGroup.items;
|
|
|
|
|
|
|
|
// Parent method
|
|
|
|
ve.ui.MWGalleryDialog.super.prototype.updateMwData.call( this, mwData );
|
|
|
|
|
|
|
|
// Get titles and captions from gallery group
|
|
|
|
this.highlightedItem.setCaption( this.highlightedCaptionInput.getValue() );
|
|
|
|
for ( i = 0, ilen = items.length; i < ilen; i++ ) {
|
2016-11-28 17:36:29 +00:00
|
|
|
extsrc += '\n' + items[ i ].imageTitle + ( items[ i ].caption ? '|' + items[ i ].caption : '' );
|
2016-03-08 21:14:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get data from options card
|
|
|
|
mode = this.modeDropdown.getMenu().getSelectedItem().getData();
|
|
|
|
caption = this.captionInput.getValue();
|
|
|
|
widths = this.widthsInput.getValue();
|
|
|
|
heights = this.heightsInput.getValue();
|
|
|
|
perrow = this.perrowInput.getValue();
|
|
|
|
showFilename = this.showFilenameCheckbox.isSelected();
|
|
|
|
classes = this.classesInput.getValue();
|
|
|
|
styles = this.stylesInput.getValue();
|
|
|
|
|
|
|
|
// Update extsrc and attributes
|
|
|
|
mwData.body.extsrc = extsrc + '\n';
|
|
|
|
mwData.attrs.mode = mode || undefined;
|
|
|
|
mwData.attrs.caption = caption || undefined;
|
2016-08-04 23:28:53 +00:00
|
|
|
mwData.attrs.widths = widths || undefined;
|
|
|
|
mwData.attrs.heights = heights || undefined;
|
2016-03-08 21:14:12 +00:00
|
|
|
mwData.attrs.perrow = perrow || undefined;
|
|
|
|
mwData.attrs.showfilename = showFilename ? 'yes' : undefined;
|
2016-12-03 13:03:02 +00:00
|
|
|
mwData.attrs.class = classes || undefined;
|
2016-11-14 22:26:39 +00:00
|
|
|
mwData.attrs.style = styles || undefined;
|
2016-08-04 23:28:53 +00:00
|
|
|
|
|
|
|
// Unset mode attribute if it is the same as the default
|
|
|
|
mwData.attrs.mode = mode === this.defaults.mode ? undefined : mode;
|
2016-03-08 21:14:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Registration */
|
|
|
|
|
|
|
|
ve.ui.windowFactory.register( ve.ui.MWGalleryDialog );
|