' ).addClass( 'cdx-tabs__list' ).attr( 'role', 'tablist' ).appendTo( $embedSwitchHeader );
[ 'wikitext', 'html' ].forEach( ( name ) => $( '
' )
.addClass( 'cdx-tabs__list__item' )
.attr( 'role', 'tab' )
.data( 'name', name )
.text( mw.message( name === 'wikitext' ? 'multimediaviewer-embed-wt' : 'multimediaviewer-embed-html' ).text() )
.on( 'click', () => this.handleTypeSwitch( name ) )
.appendTo( this.$embedSwitchList )
);
}
/**
* Creates pulldown menus to select file sizes.
*
* @param {jQuery} $container
*/
createSizePulldownMenus( $container ) {
// Wikitext sizes pulldown menu
this.$embedSizeSwitchWikitext = this.utils.createSelectMenu(
[ 'default', 'small', 'medium', 'large' ],
'default'
);
// Html sizes pulldown menu
this.$embedSizeSwitchHtml = this.utils.createSelectMenu(
[ 'small', 'medium', 'large', 'original' ],
'original'
);
$( '' ).addClass( 'mw-mmv-flex mw-mmv-mb-75' ).append(
this.$embedSizeSwitchHtml,
this.$embedSizeSwitchWikitext
).appendTo( $container );
}
/**
* Registers listeners.
*/
attach() {
// Logged-out defaults to 'html', logged-in to 'wikitext'
this.handleTypeSwitch( mw.user.isAnon() ? 'html' : 'wikitext' );
// Register handlers for switching between file sizes
this.$embedSizeSwitchHtml.on( 'change', () => this.handleSizeSwitch() );
this.$embedSizeSwitchWikitext.on( 'change', () => this.handleSizeSwitch() );
}
/**
* Clears listeners.
*/
unattach() {
super.unattach();
this.$embedSizeSwitchHtml.off( 'change' );
this.$embedSizeSwitchWikitext.off( 'change' );
}
/**
* Handles size menu change events.
*/
handleSizeSwitch() {
// eslint-disable-next-line no-jquery/no-sizzle
const $html = this.$embedSizeSwitchHtml.find( ':selected' );
if ( $html.length ) {
this.updateEmbedHtml( {}, $html.data( 'width' ), $html.data( 'height' ) );
}
// eslint-disable-next-line no-jquery/no-sizzle
const $wikitext = this.$embedSizeSwitchWikitext.find( ':selected' );
if ( $wikitext.length ) {
this.updateEmbedWikitext( $wikitext.data( 'width' ) );
}
}
/**
* Handles snippet type switch.
*
* @param {string} value 'html' or 'wikitext'
*/
handleTypeSwitch( value ) {
this.$embedSwitchList.children().each( ( _i, element ) => {
const $element = $( element );
$element.attr( 'aria-selected', $element.data( 'name' ) === value );
} );
this.$embedTextHtmlDiv.toggle( value === 'html' );
this.$embedSizeSwitchHtml.toggle( value === 'html' );
this.$embedTextWikitextDiv.toggle( value === 'wikitext' );
this.$embedSizeSwitchWikitext.toggle( value === 'wikitext' );
}
/**
* Reset current menu selection to default item.
*/
resetCurrentSizeMenuToDefault() {
this.$embedSizeSwitchWikitext.val( 'default' );
this.$embedSizeSwitchHtml.val( 'original' );
this.handleSizeSwitch();
}
/**
* Sets the HTML embed text.
*
* Assumes that the set() method has already been called to update this.embedFileInfo
*
* @param {Thumbnail} thumbnail (can be just an empty object)
* @param {number} width New width to set
* @param {number} height New height to set
*/
updateEmbedHtml( thumbnail, width, height ) {
if ( !this.embedFileInfo ) {
return;
}
let src = thumbnail.url || this.embedFileInfo.imageInfo.url;
// If the image dimension requested are "large", use the current image url
if ( width > Embed.LARGE_IMAGE_WIDTH_THRESHOLD || height > Embed.LARGE_IMAGE_HEIGHT_THRESHOLD ) {
src = this.embedFileInfo.imageInfo.url;
}
this.$embedTextHtml.val(
this.formatter.getThumbnailHtml( this.embedFileInfo, src, width, height )
);
}
/**
* Updates the wikitext embed text with a new value for width.
*
* Assumes that the set method has already been called.
*
* @param {number} width
*/
updateEmbedWikitext( width ) {
if ( !this.embedFileInfo ) {
return;
}
this.$embedTextWikitext.val(
this.formatter.getThumbnailWikitextFromEmbedFileInfo( this.embedFileInfo, width )
);
}
/**
* Gets size options for html and wikitext snippets.
*
* @param {number} width
* @param {number} height
* @return {Object}
* @return {Object} return.html Collection of possible image sizes for html snippets
* @return {Object} return.wikitext Collection of possible image sizes for wikitext snippets
*/
getSizeOptions( width, height ) {
const sizes = {};
sizes.html = this.utils.getPossibleImageSizesForHtml( width, height );
sizes.wikitext = this.getPossibleImageSizesForWikitext( width, height );
return sizes;
}
/**
* Sets the data on the element.
*
* @param {Image} image
* @param {Repo} repo
* @param {string} [caption]
* @param {string} [alt]
*/
set( image, repo, caption, alt ) {
const sizes = this.getSizeOptions( image.width, image.height );
this.embedFileInfo = { imageInfo: image, repoInfo: repo };
if ( caption ) {
this.embedFileInfo.caption = caption;
}
if ( alt ) {
this.embedFileInfo.alt = alt;
}
this.utils.updateSelectOptions( sizes.html, this.$embedSizeSwitchHtml.children() );
this.utils.updateSelectOptions( sizes.wikitext, this.$embedSizeSwitchWikitext.children() );
// Reset defaults
this.resetCurrentSizeMenuToDefault();
this.utils.getThumbnailUrlPromise( this.LARGE_IMAGE_WIDTH_THRESHOLD )
.done( ( thumbnail ) => {
this.updateEmbedHtml( thumbnail );
} );
}
/**
* @inheritdoc
*/
empty() {
this.$embedTextHtml.val( '' );
this.$embedTextWikitext.val( '' );
this.$embedSizeSwitchHtml.toggle( false );
this.$embedSizeSwitchWikitext.toggle( false );
}
/**
* Calculates possible image sizes for wikitext snippets. It returns up to
* three possible snippet frame sizes (small, medium, large).
*
* @param {number} width
* @param {number} height
* @return {Object}
* @return {Object} return.small
* @return {Object} return.medium
* @return {Object} return.large
*/
getPossibleImageSizesForWikitext( width, height ) {
const buckets = {
small: 300,
medium: 400,
large: 500
};
const sizes = {};
const widthToHeight = height / width;
for ( const bucketName in buckets ) {
const bucketWidth = buckets[ bucketName ];
if ( width > bucketWidth ) {
sizes[ bucketName ] = {
width: bucketWidth,
height: Math.round( bucketWidth * widthToHeight )
};
}
}
sizes.default = { width: null, height: null };
return sizes;
}
}
/**
* @property {number} Width threshold at which an image is to be considered "large"
* @static
*/
Embed.LARGE_IMAGE_WIDTH_THRESHOLD = 1200;
/**
* @property {number} Height threshold at which an image is to be considered "large"
* @static
*/
Embed.LARGE_IMAGE_HEIGHT_THRESHOLD = 900;
module.exports = Embed;
}() );