diff options
Diffstat (limited to 'www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.download.pane.js')
-rw-r--r-- | www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.download.pane.js | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.download.pane.js b/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.download.pane.js new file mode 100644 index 00000000..560695bc --- /dev/null +++ b/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.download.pane.js @@ -0,0 +1,429 @@ +/* + * 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/>. + */ + +( function ( mw, $, oo ) { + // Shortcut for prototype later + var DP; + + /** + * UI component that provides functionality to download the media asset displayed. + * + * @class mw.mmv.ui.download.Pane + * @extends mw.mmv.ui.Element + * @constructor + * @param {jQuery} $container + */ + function Pane( $container ) { + mw.mmv.ui.Element.call( this, $container ); + + /** @property {mw.mmv.ui.Utils} utils - */ + this.utils = new mw.mmv.ui.Utils(); + + this.$pane = $( '<div>' ) + .addClass( 'mw-mmv-download-pane' ) + .appendTo( this.$container ); + + this.$downloadArea = $( '<div>' ) + .addClass( 'mw-mmv-download-area' ) + .appendTo( this.$pane ); + + this.createDownloadButton( this.$downloadArea ); + this.createSizePulldownMenu( this.$downloadArea ); + this.createPreviewLink( this.$downloadArea ); + + this.formatter = new mw.mmv.EmbedFileFormatter(); + this.currentAttrView = 'plain'; + this.createAttributionButton( this.$pane ); + + /** + * Default item for the size menu. + * @property {OO.ui.MenuOptionWidget} + */ + this.defaultItem = this.downloadSizeMenu.getMenu().findSelectedItem(); + + /** @property {mw.mmv.model.Image|null} Image the download button currently points to. */ + this.image = null; + } + oo.inheritClass( Pane, mw.mmv.ui.Element ); + DP = Pane.prototype; + + /** + * @event mmv-download-cta-open + * Fired when the attribution call to action panel is clicked. + */ + /** + * @event mmv-download-cta-close + * Fired when the attribution area is closed. + */ + + /** + * 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 + */ + DP.createDownloadButton = function ( $container ) { + // TODO: Use OOUI progressive button widget instead + this.$downloadButton = $( '<a>' ) + .attr( 'target', '_blank' ) + .attr( 'download', '' ) + .addClass( 'mw-ui-button mw-ui-progressive mw-mmv-download-go-button' ) + .click( function () { + mw.mmv.actionLogger.log( 'download' ); + } ); + + this.$selectionArrow = $( '<span>' ) + .addClass( 'mw-ui-button mw-ui-progressive mw-mmv-download-select-menu' ) + .append( + $( '<span>' ) + .addClass( 'mw-mmv-download-image-size-name' ) + .html( ' ' ) + ) + .append( + $( '<span>' ) + .addClass( 'mw-mmv-download-image-size' ) + .html( ' ' ) + ); + + $container + .append( this.$downloadButton ) + .append( this.$selectionArrow ); + }; + + /** + * Creates pulldown menu to select image sizes. + * + * @param {jQuery} $container + */ + DP.createSizePulldownMenu = function ( $container ) { + this.downloadSizeMenu = this.utils.createPulldownMenu( + [ 'original', 'small', 'medium', 'large' ], + [ 'mw-mmv-download-size' ], + 'original' + ); + + this.downloadSizeMenu.getMenu().on( 'select', function ( item ) { + mw.mmv.actionLogger.log( 'download-select-menu-' + item.data.name ); + } ); + + $container.append( this.downloadSizeMenu.$element ); + }; + + /** + * Creates preview link. + * + * @param {jQuery} $container + */ + DP.createPreviewLink = function ( $container ) { + this.$previewLink = $( '<a>' ) + .attr( 'target', '_blank' ) + .addClass( 'mw-mmv-download-preview-link' ) + .text( mw.message( 'multimediaviewer-download-preview-link-title' ).text() ) + .appendTo( $container ) + .click( function () { + mw.mmv.actionLogger.log( 'download-view-in-browser' ); + } ); + }; + + DP.createAttributionButton = function ( $container ) { + var dl = this, + attributionInput = new oo.ui.TextInputWidget( { + classes: [ 'mw-mmv-download-attr-input' ], + readOnly: true + } ), + attributionSwitch = new oo.ui.ButtonSelectWidget( { + classes: [ 'mw-mmv-download-attr-select' ] + } ), + plainOption = new oo.ui.ButtonOptionWidget( { + data: 'plain', + label: mw.message( 'multimediaviewer-attr-plain' ).text() + } ), + htmlOption = new oo.ui.ButtonOptionWidget( { + data: 'html', + label: mw.message( 'multimediaviewer-attr-html' ).text() + } ); + + attributionSwitch.addItems( [ + plainOption, + htmlOption + ] ); + + attributionSwitch.selectItem( plainOption ); + + attributionSwitch.on( 'select', function ( selection ) { + dl.selectAttribution( selection.getData() ); + + dl.attributionInput.$element.find( 'input' ).focus(); + } ); + + this.$attributionSection = $( '<div>' ) + .addClass( 'mw-mmv-download-attribution mw-mmv-download-attribution-collapsed' ) + .appendTo( $container ) + .click( function () { + if ( dl.$attributionSection.hasClass( 'mw-mmv-download-attribution-collapsed' ) ) { + dl.$container.trigger( 'mmv-download-cta-open' ); + dl.$attributionSection.removeClass( 'mw-mmv-download-attribution-collapsed' ); + dl.attributionInput.$element.find( 'input' ).focus(); + } + } ); + + this.$attributionCtaHeader = $( '<p>' ) + .addClass( 'mw-mmv-download-attribution-cta-header' ) + .text( mw.message( 'multimediaviewer-download-attribution-cta-header' ).text() ); + this.$attributionCta = $( '<div>' ) + .addClass( 'mw-mmv-download-attribution-cta' ) + .append( + this.$attributionCtaHeader, + $( '<p>' ) + .addClass( 'mw-mmv-download-attribution-cta-invite' ) + .text( mw.message( 'multimediaviewer-download-attribution-cta' ).text() ) + ) + .appendTo( this.$attributionSection ); + this.attributionInput = attributionInput; + this.$attributionCopy = this.$copyButton = $( '<button>' ) + .addClass( 'mw-ui-button mw-mmv-button mw-mmv-dialog-copy' ) + .click( function () { + // Select the text, and then try to copy the text. + // If the copy fails or is not supported, continue as if nothing had happened. + dl.attributionInput.select(); + try { + if ( document.queryCommandSupported && + document.queryCommandSupported( 'copy' ) ) { + document.execCommand( 'copy' ); + } + } catch ( e ) { + // queryCommandSupported in Firefox pre-41 can throw errors when used with + // clipboard commands. We catch and ignore these and other copy-command-related + // errors here. + } + } ) + .prop( 'title', mw.msg( 'multimediaviewer-download-attribution-copy' ) ) + .text( mw.msg( 'multimediaviewer-download-attribution-copy' ) ) + .tipsy( { + delayIn: mw.config.get( 'wgMultimediaViewer' ).tooltipDelay, + gravity: this.correctEW( 'se' ) + } ); + + this.$attributionHowHeader = $( '<p>' ) + .addClass( 'mw-mmv-download-attribution-how-header' ) + .text( mw.message( 'multimediaviewer-download-attribution-cta-header' ).text() ); + this.$attributionHow = $( '<div>' ) + .addClass( 'mw-mmv-download-attribution-how' ) + .append( + this.$attributionHowHeader, + this.attributionInput.$element, + this.$attributionCopy, + attributionSwitch.$element, + $( '<p>' ) + .addClass( 'mw-mmv-download-attribution-close-button' ) + .click( function ( e ) { + dl.$container.trigger( 'mmv-download-cta-close' ); + dl.$attributionSection.addClass( 'mw-mmv-download-attribution-collapsed' ); + e.stopPropagation(); + } ) + .text( ' ' ) + ) + .appendTo( this.$attributionSection ); + }; + + /** + * Selects the specified attribution type. + * + * @param {string} [name='plain'] The attribution type to use ('plain' or 'html') + */ + DP.selectAttribution = function ( name ) { + this.currentAttrView = name; + + if ( this.currentAttrView === 'html' ) { + this.attributionInput.setValue( this.htmlCredit ); + } else { + this.attributionInput.setValue( this.textCredit ); + } + }; + + /** + * Registers listeners. + */ + DP.attach = function () { + var download = this; + + // Register handlers for switching between file sizes + this.downloadSizeMenu.getMenu().on( 'choose', function ( item ) { + download.handleSizeSwitch( item ); + } ); + this.$selectionArrow.on( 'click', function () { + download.downloadSizeMenu.getMenu().toggle(); + } ); + + this.attributionInput.$element.find( 'input' ) + .on( 'focus', this.selectAllOnEvent ) + .on( 'mousedown click', this.onlyFocus ); + }; + + /** + * Clears listeners. + */ + DP.unattach = function () { + mw.mmv.ui.Element.prototype.unattach.call( this ); + + this.downloadSizeMenu.getMenu().off( 'choose' ); + this.$selectionArrow.off( 'click' ); + + this.attributionInput.$element.find( 'input' ) + .off( 'focus mousedown click' ); + }; + + /** + * Handles size menu change events. + * + * @param {OO.ui.MenuOptionWidget} item + */ + DP.handleSizeSwitch = function ( item ) { + var download = this, + value = item.getData(); + + if ( value.name === 'original' && this.image !== null ) { + this.setDownloadUrl( this.image.url ); + this.setButtonText( value.name, this.getExtensionFromUrl( this.image.url ), + value.width, value.height ); + } else { + // Disable download while we get the image + this.$downloadButton.addClass( 'disabledLink' ); + // Set a temporary message. It will be updated once we have the file type. + this.setButtonText( value.name, this.imageExtension, value.width, value.height ); + + this.utils.getThumbnailUrlPromise( value.width ).done( function ( thumbnail ) { + download.setDownloadUrl( thumbnail.url ); + download.setButtonText( value.name, download.getExtensionFromUrl( thumbnail.url ), + value.width, value.height ); + } ); + } + }; + + /** + * Sets the URL on the download button. + * + * @param {string} url + */ + DP.setDownloadUrl = function ( url ) { + this.$downloadButton.attr( 'href', url + '?download' ); + this.$previewLink.attr( 'href', url ); + + // Re-enable download + this.$downloadButton.removeClass( 'disabledLink' ); + }; + + /** + * Sets the text of the download button. + * + * @param {string} sizeClass A size class such as 'small' + * @param {string} extension file extension + * @param {number} width + * @param {number} height + */ + DP.setButtonText = function ( sizeClass, extension, width, height ) { + var sizeClasMessage, sizeMessage, dimensionMessage; + + sizeClasMessage = mw.message( 'multimediaviewer-download-' + sizeClass + '-button-name' ).text(); + dimensionMessage = mw.message( 'multimediaviewer-embed-dimensions', width, height ).text(); + sizeMessage = mw.message( 'multimediaviewer-embed-dimensions-with-file-format', + dimensionMessage, extension ).text(); + + // Update button label and size strings to reflect new selected size + this.$downloadButton.html( + '<span class="mw-mmv-download-image-size-name">' + sizeClasMessage + '</span>' + + '<span class="mw-mmv-download-image-size">' + sizeMessage + '</span>' + ); + }; + + /** + * Sets the text in the attribution input element. + * + * @param {mw.mmv.model.EmbedFileInfo} embed + */ + DP.setAttributionText = function ( embed ) { + this.htmlCredit = this.formatter.getCreditHtml( embed ); + this.textCredit = this.formatter.getCreditText( embed ); + this.selectAttribution( this.currentAttrView ); + }; + + /** + * Chops off the extension part of an URL. + * + * @param {string} url URL + * @return {string} Extension + */ + DP.getExtensionFromUrl = function ( url ) { + var urlParts = url.split( '.' ); + return urlParts[ urlParts.length - 1 ]; + }; + + /** + * Sets the data on the element. + * + * @param {mw.mmv.model.Image} image + * @param {mw.mmv.model.Repo} repo + */ + DP.set = function ( image, repo ) { + var attributionCtaMessage, + license = image && image.license, + sizeOptions = this.downloadSizeMenu.getMenu().getItems(), + sizes = this.utils.getPossibleImageSizesForHtml( image.width, image.height ); + + this.image = image; + + this.utils.updateMenuOptions( sizes, sizeOptions ); + + this.downloadSizeMenu.$element.addClass( 'active' ); + + // 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 + this.downloadSizeMenu.getMenu().chooseItem( this.defaultItem ); + + if ( image && repo ) { + this.setAttributionText( new mw.mmv.model.EmbedFileInfo( image, repo ) ); + } + + attributionCtaMessage = ( license && license.needsAttribution() ) ? + 'multimediaviewer-download-attribution-cta-header' : + 'multimediaviewer-download-optional-attribution-cta-header'; + this.$attributionCtaHeader.text( mw.message( attributionCtaMessage ).text() ); + this.$attributionHowHeader.text( mw.message( attributionCtaMessage ).text() ); + }; + + /** + * @inheritdoc + */ + DP.empty = function () { + this.downloadSizeMenu.getMenu().toggle( false ); + this.downloadSizeMenu.$element.removeClass( 'active' ); + + this.$downloadButton.attr( 'href', '' ); + this.$previewLink.attr( 'href', '' ); + this.imageExtension = undefined; + + this.image = null; + }; + + mw.mmv.ui.download.Pane = Pane; +}( mediaWiki, jQuery, OO ) ); |