2014-03-31 16:08:02 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the MediaWiki extension MultimediaViewer.
|
|
|
|
*
|
|
|
|
* MultimediaViewer is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* MultimediaViewer is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2023-05-19 20:26:45 +00:00
|
|
|
const { UiElement } = require( 'mmv' );
|
2023-05-20 06:42:20 +00:00
|
|
|
const { EmbedFileFormatter, Utils } = require( 'mmv.ui.ondemandshareddependencies' );
|
2023-05-19 20:26:45 +00:00
|
|
|
|
2018-11-12 16:33:24 +00:00
|
|
|
( function () {
|
2014-03-31 16:08:02 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* UI component that provides functionality to download the media asset displayed.
|
|
|
|
*/
|
2023-05-20 12:38:59 +00:00
|
|
|
class DownloadPane extends UiElement {
|
|
|
|
/**
|
|
|
|
* @param {jQuery} $container
|
|
|
|
*/
|
|
|
|
constructor( $container ) {
|
|
|
|
super( $container );
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
this.formatter = new EmbedFileFormatter();
|
2024-05-04 08:11:42 +00:00
|
|
|
this.createDownloadSection( this.$container );
|
|
|
|
this.createAttributionButton( this.$container );
|
2023-05-20 12:38:59 +00:00
|
|
|
|
|
|
|
/** @property {Image|null} Image the download button currently points to. */
|
|
|
|
this.image = null;
|
|
|
|
}
|
2014-06-12 23:59:06 +00:00
|
|
|
|
2014-04-02 02:22:16 +00:00
|
|
|
/**
|
2024-05-04 08:11:42 +00:00
|
|
|
* Creates dialog download section.
|
2023-06-27 20:10:10 +00:00
|
|
|
*
|
2024-05-04 08:11:42 +00:00
|
|
|
* @param {jQuery} $container
|
2023-05-20 12:38:59 +00:00
|
|
|
*/
|
2024-05-04 08:11:42 +00:00
|
|
|
createDownloadSection( $container ) {
|
|
|
|
const $header = $( '<div>' )
|
|
|
|
.addClass( 'cdx-dialog__header' )
|
|
|
|
.appendTo( $container );
|
|
|
|
$( '<div>' )
|
|
|
|
.addClass( 'cdx-dialog__header__title' )
|
|
|
|
.text( mw.message( 'multimediaviewer-download-link' ).text() )
|
|
|
|
.appendTo( $header );
|
2023-05-20 13:02:55 +00:00
|
|
|
|
2024-05-04 08:11:42 +00:00
|
|
|
const $body = $( '<div>' )
|
|
|
|
.addClass( 'cdx-dialog__body mw-mmv-pt-0' )
|
|
|
|
.appendTo( $container );
|
|
|
|
|
|
|
|
this.$downloadArea = $( '<div>' )
|
|
|
|
.addClass( 'mw-mmv-flex mw-mmv-gap-50' )
|
|
|
|
.appendTo( $body );
|
|
|
|
this.createSizePulldownMenu( this.$downloadArea );
|
|
|
|
this.createDownloadButton( this.$downloadArea );
|
|
|
|
|
|
|
|
const $p = $( '<p>' ).addClass( 'mw-mmv-mt-75' ).appendTo( $body );
|
|
|
|
this.createPreviewLink( $p );
|
|
|
|
}
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Creates download split button. It is a link with the "download" property set plus an
|
|
|
|
* arrow that allows the user to select the image size desired. The "download" property
|
|
|
|
* triggers native browser downloading in browsers that support it. The fallback is the
|
|
|
|
* 'download' parameter which instructs the server to send the right headers so the browser
|
|
|
|
* downloads the file instead of just displaying it. If all this fails, the image will appear
|
|
|
|
* in another window/tab.
|
|
|
|
*
|
|
|
|
* @param {jQuery} $container
|
|
|
|
*/
|
|
|
|
createDownloadButton( $container ) {
|
|
|
|
this.$downloadButton = $( '<a>' )
|
|
|
|
.attr( 'target', '_blank' )
|
|
|
|
.attr( 'download', '' )
|
2024-05-04 08:11:42 +00:00
|
|
|
.addClass( 'cdx-button cdx-button--weight-primary cdx-button--action-progressive cdx-button--fake-button cdx-button--fake-button--enabled' )
|
2024-05-04 19:37:24 +00:00
|
|
|
// FIXME T364254: using "notheme" here since codex does not apply @color-inverted-fixed instead of @color-inverted for progressive/destructive button
|
|
|
|
.html( '<span class="cdx-button__icon cdx-button__icon--download notheme" aria-hidden="true"></span>' + mw.message( 'multimediaviewer-download' ).text() )
|
2024-05-04 08:11:42 +00:00
|
|
|
.appendTo( $container );
|
2023-05-20 12:38:59 +00:00
|
|
|
}
|
2014-12-07 08:09:04 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Creates pulldown menu to select image sizes.
|
|
|
|
*
|
|
|
|
* @param {jQuery} $container
|
|
|
|
*/
|
|
|
|
createSizePulldownMenu( $container ) {
|
2024-05-16 19:43:44 +00:00
|
|
|
this.$downloadSizeMenu = Utils.createSelectMenu(
|
2023-05-20 12:38:59 +00:00
|
|
|
[ 'original', 'small', 'medium', 'large', 'xl' ],
|
|
|
|
'original'
|
2024-05-04 08:11:42 +00:00
|
|
|
).appendTo( $container );
|
2023-05-20 12:38:59 +00:00
|
|
|
}
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Creates preview link.
|
|
|
|
*
|
|
|
|
* @param {jQuery} $container
|
|
|
|
*/
|
|
|
|
createPreviewLink( $container ) {
|
|
|
|
this.$previewLink = $( '<a>' )
|
|
|
|
.attr( 'target', '_blank' )
|
2024-05-04 08:11:42 +00:00
|
|
|
.addClass( 'cdx-docs-link' )
|
|
|
|
.html( mw.message( 'multimediaviewer-download-preview-link-title' ).text() )
|
2023-05-20 12:38:59 +00:00
|
|
|
.appendTo( $container );
|
|
|
|
}
|
2024-02-13 00:44:51 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
createAttributionButton( $container ) {
|
2024-05-16 19:43:44 +00:00
|
|
|
[ this.$attributionInput, this.$attributionInputDiv ] = Utils.createInputWithCopy(
|
2024-05-04 14:00:17 +00:00
|
|
|
mw.message( 'multimediaviewer-download-attribution-copy' ).text(), ''
|
|
|
|
);
|
2023-05-20 12:38:59 +00:00
|
|
|
|
2024-05-04 08:11:42 +00:00
|
|
|
const $header = $( '<div>' )
|
|
|
|
.addClass( 'cdx-dialog__header' )
|
|
|
|
.appendTo( $container );
|
|
|
|
$( '<p>' )
|
|
|
|
.addClass( 'cdx-dialog__header__title' )
|
|
|
|
.text( mw.message( 'multimediaviewer-download-attribution' ).text() )
|
|
|
|
.appendTo( $header );
|
2023-05-20 12:38:59 +00:00
|
|
|
this.$attributionHowHeader = $( '<p>' )
|
2024-05-04 08:11:42 +00:00
|
|
|
.addClass( 'mw-mmv-mb-75' )
|
2023-05-20 12:38:59 +00:00
|
|
|
.text( mw.message( 'multimediaviewer-download-attribution-cta-header' ).text() );
|
2024-05-04 08:11:42 +00:00
|
|
|
|
|
|
|
const $attributionTabs = $( '<div>' ).addClass( 'cdx-tabs' );
|
|
|
|
const $attributionTabsHeader = $( '<div>' ).addClass( 'cdx-tabs__header' ).appendTo( $attributionTabs );
|
|
|
|
this.$attributionTabsList = $( '<div>' ).addClass( 'cdx-tabs__list' ).attr( 'role', 'tablist' ).appendTo( $attributionTabsHeader );
|
|
|
|
[ 'plain', 'html' ].forEach( ( name ) => $( '<button>' )
|
|
|
|
.addClass( 'cdx-tabs__list__item' )
|
|
|
|
.attr( 'role', 'tab' )
|
2024-05-15 18:28:43 +00:00
|
|
|
.data( 'name', name )
|
2024-05-04 08:11:42 +00:00
|
|
|
// The following messages are used here:
|
|
|
|
// * multimediaviewer-attr-plain
|
|
|
|
// * multimediaviewer-attr-html
|
|
|
|
.text( mw.message( 'multimediaviewer-attr-' + name ).text() )
|
|
|
|
.on( 'click', () => this.selectAttribution( name ) )
|
|
|
|
.appendTo( this.$attributionTabsList )
|
|
|
|
);
|
|
|
|
this.selectAttribution( 'plain' );
|
|
|
|
|
|
|
|
$( '<div>' )
|
|
|
|
.addClass( 'cdx-dialog__body mw-mmv-pt-0 mw-mmv-pb-150' )
|
2023-05-20 12:38:59 +00:00
|
|
|
.append(
|
|
|
|
this.$attributionHowHeader,
|
2024-05-04 08:11:42 +00:00
|
|
|
$attributionTabs,
|
2024-05-04 14:00:17 +00:00
|
|
|
this.$attributionInputDiv.addClass( ' mw-mmv-mt-75' )
|
2023-05-20 12:38:59 +00:00
|
|
|
)
|
2024-05-04 08:11:42 +00:00
|
|
|
.appendTo( $container );
|
2023-05-20 12:38:59 +00:00
|
|
|
}
|
2014-06-12 23:59:06 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Selects the specified attribution type.
|
|
|
|
*
|
|
|
|
* @param {string} [name='plain'] The attribution type to use ('plain' or 'html')
|
|
|
|
*/
|
|
|
|
selectAttribution( name ) {
|
|
|
|
this.currentAttrView = name;
|
|
|
|
|
2024-05-04 08:11:42 +00:00
|
|
|
this.$attributionTabsList.children().each( ( _i, element ) => {
|
|
|
|
const $element = $( element );
|
2024-05-15 18:28:43 +00:00
|
|
|
$element.attr( 'aria-selected', $element.data( 'name' ) === name );
|
2024-05-04 08:11:42 +00:00
|
|
|
} );
|
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
if ( this.currentAttrView === 'html' ) {
|
2024-05-04 08:11:42 +00:00
|
|
|
this.$attributionInput.val( this.htmlCredit );
|
2023-05-20 12:38:59 +00:00
|
|
|
} else {
|
2024-05-04 08:11:42 +00:00
|
|
|
this.$attributionInput.val( this.textCredit );
|
2023-05-20 12:38:59 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-12 23:59:06 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Registers listeners.
|
|
|
|
*/
|
|
|
|
attach() {
|
|
|
|
// Register handlers for switching between file sizes
|
2024-05-04 08:11:42 +00:00
|
|
|
this.$downloadSizeMenu.on( 'change', () => this.handleSizeSwitch() );
|
2014-06-12 23:59:06 +00:00
|
|
|
}
|
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Clears listeners.
|
|
|
|
*/
|
|
|
|
unattach() {
|
|
|
|
super.unattach();
|
2024-05-04 08:11:42 +00:00
|
|
|
this.$downloadSizeMenu.off( 'change' );
|
2023-05-20 12:38:59 +00:00
|
|
|
}
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Handles size menu change events.
|
|
|
|
*/
|
2024-05-04 08:11:42 +00:00
|
|
|
handleSizeSwitch() {
|
|
|
|
// eslint-disable-next-line no-jquery/no-sizzle
|
|
|
|
const $option = this.$downloadSizeMenu.find( ':selected' );
|
|
|
|
const value = {
|
2024-05-15 18:28:43 +00:00
|
|
|
name: $option.data( 'name' ),
|
|
|
|
width: $option.data( 'width' ),
|
|
|
|
height: $option.data( 'height' )
|
2024-05-04 08:11:42 +00:00
|
|
|
};
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
if ( value.name === 'original' && this.image !== null ) {
|
|
|
|
this.setDownloadUrl( this.image.url );
|
|
|
|
} else {
|
|
|
|
// Disable download while we get the image
|
|
|
|
this.$downloadButton.addClass( 'disabledLink' );
|
2024-05-16 19:43:44 +00:00
|
|
|
Utils.getThumbnailUrlPromise( value.width ).done( ( thumbnail ) => {
|
2023-05-20 12:38:59 +00:00
|
|
|
this.setDownloadUrl( thumbnail.url );
|
|
|
|
} );
|
|
|
|
}
|
2014-04-21 17:17:11 +00:00
|
|
|
}
|
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Sets the URL on the download button.
|
|
|
|
*
|
|
|
|
* @param {string} url
|
|
|
|
*/
|
|
|
|
setDownloadUrl( url ) {
|
2024-02-13 00:44:51 +00:00
|
|
|
this.$downloadButton.attr( 'href', `${ url }?download` );
|
2023-05-20 12:38:59 +00:00
|
|
|
this.$previewLink.attr( 'href', url );
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
// Re-enable download
|
|
|
|
this.$downloadButton.removeClass( 'disabledLink' );
|
|
|
|
}
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Sets the text in the attribution input element.
|
|
|
|
*
|
|
|
|
* @param {Object} embed
|
|
|
|
* @param {Image} embed.imageInfo
|
|
|
|
* @param {Repo} embed.repoInfo
|
|
|
|
*/
|
|
|
|
setAttributionText( embed ) {
|
|
|
|
this.htmlCredit = this.formatter.getCreditHtml( embed );
|
|
|
|
this.textCredit = this.formatter.getCreditText( embed );
|
|
|
|
this.selectAttribution( this.currentAttrView );
|
|
|
|
}
|
2014-06-12 23:59:06 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Chops off the extension part of an URL.
|
|
|
|
*
|
|
|
|
* @param {string} url URL
|
|
|
|
* @return {string} Extension
|
|
|
|
*/
|
|
|
|
getExtensionFromUrl( url ) {
|
|
|
|
const urlParts = url.split( '.' );
|
|
|
|
return urlParts[ urlParts.length - 1 ];
|
2014-06-12 23:59:06 +00:00
|
|
|
}
|
2014-11-24 22:09:03 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* Sets the data on the element.
|
|
|
|
*
|
|
|
|
* @param {Image} image
|
|
|
|
* @param {Repo} repo
|
|
|
|
*/
|
|
|
|
set( image, repo ) {
|
|
|
|
const license = image && image.license;
|
2024-05-16 19:43:44 +00:00
|
|
|
const sizes = Utils.getPossibleImageSizesForHtml( image.width, image.height );
|
2023-05-20 12:38:59 +00:00
|
|
|
|
|
|
|
this.image = image;
|
|
|
|
|
2024-05-16 19:43:44 +00:00
|
|
|
Utils.updateSelectOptions( sizes, this.$downloadSizeMenu.children() );
|
2023-05-20 12:38:59 +00:00
|
|
|
|
|
|
|
// Note: This extension will not be the real one for file types other than: png/gif/jpg/jpeg
|
|
|
|
this.imageExtension = image.title.getExtension().toLowerCase();
|
|
|
|
|
|
|
|
// Reset size menu to default item and update download button label now that we have the info
|
2024-05-04 08:11:42 +00:00
|
|
|
this.$downloadSizeMenu.val( 'original' );
|
|
|
|
this.handleSizeSwitch();
|
2023-05-20 12:38:59 +00:00
|
|
|
|
|
|
|
if ( image && repo ) {
|
|
|
|
const embedFileInfo = {
|
|
|
|
imageInfo: image,
|
|
|
|
repoInfo: repo
|
|
|
|
};
|
|
|
|
this.setAttributionText( embedFileInfo );
|
|
|
|
}
|
|
|
|
|
|
|
|
const attributionCtaMessage = ( license && license.needsAttribution() ) ?
|
|
|
|
'multimediaviewer-download-attribution-cta-header' :
|
|
|
|
'multimediaviewer-download-optional-attribution-cta-header';
|
|
|
|
// Message defined above
|
|
|
|
// eslint-disable-next-line mediawiki/msg-doc
|
|
|
|
this.$attributionHowHeader.text( mw.message( attributionCtaMessage ).text() );
|
|
|
|
}
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
empty() {
|
|
|
|
this.$downloadButton.attr( 'href', '' );
|
|
|
|
this.$previewLink.attr( 'href', '' );
|
|
|
|
this.imageExtension = undefined;
|
2014-04-21 17:17:11 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
this.image = null;
|
|
|
|
}
|
|
|
|
}
|
2014-03-31 16:08:02 +00:00
|
|
|
|
2023-05-20 12:38:59 +00:00
|
|
|
module.exports = DownloadPane;
|
2018-11-12 16:33:24 +00:00
|
|
|
}() );
|