summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.reuse.embed.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.reuse.embed.js')
-rw-r--r--www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.reuse.embed.js542
1 files changed, 542 insertions, 0 deletions
diff --git a/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.reuse.embed.js b/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.reuse.embed.js
new file mode 100644
index 00000000..bdf03aff
--- /dev/null
+++ b/www/wiki/extensions/MultimediaViewer/resources/mmv/ui/mmv.ui.reuse.embed.js
@@ -0,0 +1,542 @@
+/*
+ * 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 EP;
+
+ /**
+ * UI component that provides the user html/wikitext snippets needed to share
+ * and/or embed a media asset.
+ *
+ * @class mw.mmv.ui.reuse.Embed
+ * @extends mw.mmv.ui.reuse.Tab
+ * @constructor
+ * @param {jQuery} $container
+ */
+ function Embed( $container ) {
+ mw.mmv.ui.reuse.Tab.call( this, $container );
+
+ /**
+ * Formatter converting image data into formats needed for output
+ *
+ * @property {mw.mmv.EmbedFileFormatter}
+ */
+ this.formatter = new mw.mmv.EmbedFileFormatter();
+
+ /** @property {mw.mmv.ui.Utils} utils - */
+ this.utils = new mw.mmv.ui.Utils();
+
+ /**
+ * Indicates whether or not the default option has been reset for both size menus.
+ *
+ * @property {boolean}
+ */
+ this.isSizeMenuDefaultReset = false;
+
+ this.$pane.addClass( 'mw-mmv-embed-pane' );
+
+ this.$pane.appendTo( this.$container );
+
+ this.createSnippetTextAreas( this.$pane );
+
+ this.$explanation = $( '<div>' )
+ .addClass( 'mw-mmv-shareembed-explanation mw-mmv-embed-explanation' )
+ .text( mw.message( 'multimediaviewer-embed-explanation' ).text() )
+ .appendTo( this.$pane );
+
+ this.createSnippetSelectionButtons( this.$pane );
+ this.createSizePulldownMenus( this.$pane );
+
+ /**
+ * Currently selected embed snippet.
+ *
+ * @property {jQuery}
+ */
+ this.$currentMainEmbedText = mw.user.isAnon() ? this.embedTextHtml.$element : this.embedTextWikitext.$element;
+
+ /**
+ * Default item for the html size menu.
+ *
+ * @property {OO.ui.MenuOptionWidget}
+ */
+ this.defaultHtmlItem = this.embedSizeSwitchHtml.getMenu().findSelectedItem();
+
+ /**
+ * Default item for the wikitext size menu.
+ *
+ * @property {OO.ui.MenuOptionWidget}
+ */
+ this.defaultWikitextItem = this.embedSizeSwitchWikitext.getMenu().findSelectedItem();
+
+ /**
+ * Currently selected size menu.
+ *
+ * @property {OO.ui.MenuSelectWidget}
+ */
+ this.currentSizeMenu = mw.user.isAnon() ? this.embedSizeSwitchHtml.getMenu() : this.embedSizeSwitchWikitext.getMenu();
+
+ /**
+ * Current default item.
+ *
+ * @property {OO.ui.MenuOptionWidget}
+ */
+ this.currentDefaultItem = mw.user.isAnon() ? this.defaultHtmlItem : this.defaultWikitextItem;
+ }
+ oo.inheritClass( Embed, mw.mmv.ui.reuse.Tab );
+ EP = Embed.prototype;
+
+ /** @property {number} Width threshold at which an image is to be considered "large" */
+ EP.LARGE_IMAGE_WIDTH_THRESHOLD = 1200;
+
+ /** @property {number} Height threshold at which an image is to be considered "large" */
+ EP.LARGE_IMAGE_HEIGHT_THRESHOLD = 900;
+
+ /**
+ * Creates text areas for html and wikitext snippets.
+ *
+ * @param {jQuery} $container
+ */
+ EP.createSnippetTextAreas = function ( $container ) {
+ var wikitextClasses = [ 'mw-mmv-embed-text-wikitext' ],
+ htmlClasses = [ 'mw-mmv-embed-text-html' ];
+
+ ( mw.user.isAnon() ? htmlClasses : wikitextClasses ).push( 'active' );
+
+ this.embedTextHtml = new oo.ui.MultilineTextInputWidget( {
+ classes: htmlClasses,
+ readOnly: true
+ } );
+
+ this.embedTextHtml.$element.find( 'textarea' )
+ .prop( 'placeholder', mw.message( 'multimediaviewer-reuse-loading-placeholder' ).text() );
+
+ this.embedTextHtml.$input.on( 'copy', function () {
+ mw.mmv.actionLogger.log( 'embed-html-copied' );
+ } );
+
+ this.embedTextWikitext = new oo.ui.MultilineTextInputWidget( {
+ classes: wikitextClasses,
+ readOnly: true
+ } );
+
+ this.embedTextWikitext.$element.find( 'textarea' )
+ .prop( 'placeholder', mw.message( 'multimediaviewer-reuse-loading-placeholder' ).text() );
+
+ this.embedTextWikitext.$input.on( 'copy', function () {
+ mw.mmv.actionLogger.log( 'embed-wikitext-copied' );
+ } );
+
+ this.$copyButton = $( '<button>' )
+ .addClass( '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.
+ $( this ).parent().find( '.active > textarea' ).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-reuse-copy-embed' ) )
+ .text( mw.msg( 'multimediaviewer-reuse-copy-embed' ) )
+ .tipsy( {
+ delayIn: mw.config.get( 'wgMultimediaViewer' ).tooltipDelay,
+ gravity: this.correctEW( 'se' )
+ } );
+
+ $( '<p>' )
+ .append(
+ this.embedTextHtml.$element,
+ this.embedTextWikitext.$element,
+ this.$copyButton
+ )
+ .appendTo( $container );
+ };
+
+ /**
+ * Creates snippet selection buttons.
+ *
+ * @param {jQuery} $container
+ */
+ EP.createSnippetSelectionButtons = function ( $container ) {
+ var wikitextButtonOption,
+ htmlButtonOption;
+
+ this.embedSwitch = new oo.ui.ButtonSelectWidget( {
+ classes: [ 'mw-mmv-embed-select' ]
+ } );
+
+ wikitextButtonOption = new oo.ui.ButtonOptionWidget( {
+ data: 'wikitext',
+ label: mw.message( 'multimediaviewer-embed-wt' ).text()
+ } );
+ htmlButtonOption = new oo.ui.ButtonOptionWidget( {
+ data: 'html',
+ label: mw.message( 'multimediaviewer-embed-html' ).text()
+ } );
+
+ this.embedSwitch.addItems( [
+ wikitextButtonOption,
+ htmlButtonOption
+ ] );
+
+ $( '<p>' )
+ .append( this.embedSwitch.$element )
+ .appendTo( $container );
+
+ // Logged-out defaults to 'html', logged-in to 'wikitext'
+ this.embedSwitch.selectItem( mw.user.isAnon() ? htmlButtonOption : wikitextButtonOption );
+ };
+
+ /**
+ * Creates pulldown menus to select file sizes.
+ *
+ * @param {jQuery} $container
+ */
+ EP.createSizePulldownMenus = function ( $container ) {
+ var wikitextClasses = [ 'mw-mmv-embed-size' ],
+ htmlClasses = [ 'mw-mmv-embed-size' ];
+
+ ( mw.user.isAnon() ? htmlClasses : wikitextClasses ).push( 'active' );
+
+ // Wikitext sizes pulldown menu
+ this.embedSizeSwitchWikitext = this.utils.createPulldownMenu(
+ [ 'default', 'small', 'medium', 'large' ],
+ wikitextClasses,
+ 'default'
+ );
+
+ this.embedSizeSwitchWikitext.getMenu().on( 'select', function ( item ) {
+ mw.mmv.actionLogger.log( 'embed-select-menu-wikitext-' + item.data.name );
+ } );
+
+ // Html sizes pulldown menu
+ this.embedSizeSwitchHtml = this.utils.createPulldownMenu(
+ [ 'small', 'medium', 'large', 'original' ],
+ htmlClasses,
+ 'original'
+ );
+
+ this.embedSizeSwitchHtml.getMenu().on( 'select', function ( item ) {
+ mw.mmv.actionLogger.log( 'embed-select-menu-html-' + item.data.name );
+ } );
+
+ $( '<p>' )
+ .append(
+ this.embedSizeSwitchHtml.$element,
+ this.embedSizeSwitchWikitext.$element
+ )
+ .appendTo( $container );
+ };
+
+ /**
+ * Registers listeners.
+ */
+ EP.attach = function () {
+ var embed = this,
+ $htmlTextarea = this.embedTextHtml.$element.find( 'textarea' ),
+ $wikitextTextarea = this.embedTextWikitext.$element.find( 'textarea' );
+
+ // Select all text once element gets focus
+ $htmlTextarea.on( 'focus', this.selectAllOnEvent );
+ $wikitextTextarea.on( 'focus', this.selectAllOnEvent );
+ // Disable partial text selection inside the textboxes
+ $htmlTextarea.on( 'mousedown click', this.onlyFocus );
+ $wikitextTextarea.on( 'mousedown click', this.onlyFocus );
+
+ // Register handler for switching between wikitext/html snippets
+ this.embedSwitch.on( 'select', $.proxy( embed.handleTypeSwitch, embed ) );
+
+ // Register handlers for switching between file sizes
+ this.embedSizeSwitchHtml.getMenu().on( 'choose', $.proxy( this.handleSizeSwitch, this ) );
+ this.embedSizeSwitchWikitext.getMenu().on( 'choose', $.proxy( this.handleSizeSwitch, this ) );
+ };
+
+ /**
+ * Clears listeners.
+ */
+ EP.unattach = function () {
+ var $htmlTextarea = this.embedTextHtml.$element.find( 'textarea' ),
+ $wikitextTextarea = this.embedTextWikitext.$element.find( 'textarea' );
+
+ mw.mmv.ui.reuse.Tab.prototype.unattach.call( this );
+
+ $htmlTextarea.off( 'focus mousedown click' );
+ $wikitextTextarea.off( 'focus mousedown click' );
+ this.embedSwitch.off( 'select' );
+ this.embedSizeSwitchHtml.getMenu().off( 'choose' );
+ this.embedSizeSwitchWikitext.getMenu().off( 'choose' );
+ };
+
+ /**
+ * Handles size menu change events.
+ *
+ * @param {OO.ui.MenuOptionWidget} item
+ */
+ EP.handleSizeSwitch = function ( item ) {
+ var value = item.getData();
+
+ this.changeSize( value.width, value.height );
+ };
+
+ /**
+ * Handles snippet type switch.
+ *
+ * @param {OO.ui.MenuOptionWidget} item
+ */
+ EP.handleTypeSwitch = function ( item ) {
+ var value = item.getData();
+
+ mw.mmv.actionLogger.log( 'embed-switched-to-' + value );
+
+ if ( value === 'html' ) {
+ this.$currentMainEmbedText = this.embedTextHtml.$element;
+ this.embedSizeSwitchWikitext.getMenu().toggle( false );
+
+ this.currentSizeMenu = this.embedSizeSwitchHtml.getMenu();
+ this.currentDefaultItem = this.defaultHtmlItem;
+ } else if ( value === 'wikitext' ) {
+ this.$currentMainEmbedText = this.embedTextWikitext.$element;
+ this.embedSizeSwitchHtml.getMenu().toggle( false );
+
+ this.currentSizeMenu = this.embedSizeSwitchWikitext.getMenu();
+ this.currentDefaultItem = this.defaultWikitextItem;
+ }
+
+ this.embedTextHtml.$element
+ .add( this.embedSizeSwitchHtml.$element )
+ .toggleClass( 'active', value === 'html' );
+
+ this.embedTextWikitext.$element
+ .add( this.embedSizeSwitchWikitext.$element )
+ .toggleClass( 'active', value === 'wikitext' );
+
+ // Reset current selection to default when switching the first time
+ if ( !this.isSizeMenuDefaultReset ) {
+ this.resetCurrentSizeMenuToDefault();
+ this.isSizeMenuDefaultReset = true;
+ }
+
+ this.select();
+ };
+
+ /**
+ * Reset current menu selection to default item.
+ */
+ EP.resetCurrentSizeMenuToDefault = function () {
+ this.currentSizeMenu.chooseItem( this.currentDefaultItem );
+ // Force select logic to update the selected item bar, otherwise we end up
+ // with the wrong label. This is implementation dependent and maybe it should
+ // be done via a to flag to OO.ui.SelectWidget.prototype.chooseItem()?
+ this.currentSizeMenu.emit( 'select', this.currentDefaultItem );
+ };
+
+ /**
+ * Changes the size, takes different actions based on which sort of
+ * embed is currently chosen.
+ *
+ * @param {number} width New width to set
+ * @param {number} height New height to set
+ */
+ EP.changeSize = function ( width, height ) {
+ var currentItem = this.embedSwitch.findSelectedItem();
+
+ if ( currentItem === null ) {
+ return;
+ }
+
+ switch ( currentItem.getData() ) {
+ case 'html':
+ this.updateEmbedHtml( {}, width, height );
+ break;
+ case 'wikitext':
+ this.updateEmbedWikitext( width );
+ break;
+ }
+
+ this.select();
+ };
+
+ /**
+ * Sets the HTML embed text.
+ *
+ * Assumes that the set() method has already been called to update this.embedFileInfo
+ *
+ * @param {mw.mmv.model.Thumbnail} thumbnail (can be just an empty object)
+ * @param {number} width New width to set
+ * @param {number} height New height to set
+ */
+ EP.updateEmbedHtml = function ( thumbnail, width, height ) {
+ var src;
+
+ if ( !this.embedFileInfo ) {
+ return;
+ }
+
+ src = thumbnail.url || this.embedFileInfo.imageInfo.url;
+
+ // If the image dimension requested are "large", use the current image url
+ if ( width > EP.LARGE_IMAGE_WIDTH_THRESHOLD || height > EP.LARGE_IMAGE_HEIGHT_THRESHOLD ) {
+ src = this.embedFileInfo.imageInfo.url;
+ }
+
+ this.embedTextHtml.setValue(
+ 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
+ */
+ EP.updateEmbedWikitext = function ( width ) {
+ if ( !this.embedFileInfo ) {
+ return;
+ }
+
+ this.embedTextWikitext.setValue(
+ this.formatter.getThumbnailWikitextFromEmbedFileInfo( this.embedFileInfo, width )
+ );
+ };
+
+ /**
+ * Shows the pane.
+ */
+ EP.show = function () {
+ mw.mmv.ui.reuse.Tab.prototype.show.call( this );
+ this.select();
+ };
+
+ /**
+ * 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
+ */
+ EP.getSizeOptions = function ( width, height ) {
+ var sizes = {};
+
+ sizes.html = this.utils.getPossibleImageSizesForHtml( width, height );
+ sizes.wikitext = this.getPossibleImageSizesForWikitext( width, height );
+
+ return sizes;
+ };
+
+ /**
+ * Sets the data on the element.
+ *
+ * @param {mw.mmv.model.Image} image
+ * @param {mw.mmv.model.Repo} repo
+ * @param {string} caption
+ * @param {string} alt
+ */
+ EP.set = function ( image, repo, caption, alt ) {
+ var embed = this,
+ htmlSizeSwitch = this.embedSizeSwitchHtml.getMenu(),
+ htmlSizeOptions = htmlSizeSwitch.getItems(),
+ wikitextSizeSwitch = this.embedSizeSwitchWikitext.getMenu(),
+ wikitextSizeOptions = wikitextSizeSwitch.getItems(),
+ sizes = this.getSizeOptions( image.width, image.height );
+
+ this.embedFileInfo = new mw.mmv.model.EmbedFileInfo( image, repo, caption, alt );
+
+ this.utils.updateMenuOptions( sizes.html, htmlSizeOptions );
+ this.utils.updateMenuOptions( sizes.wikitext, wikitextSizeOptions );
+
+ // Reset defaults
+ this.isSizeMenuDefaultReset = false;
+ this.resetCurrentSizeMenuToDefault();
+
+ this.utils.getThumbnailUrlPromise( this.LARGE_IMAGE_WIDTH_THRESHOLD )
+ .done( function ( thumbnail ) {
+ embed.updateEmbedHtml( thumbnail );
+ embed.select();
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ EP.empty = function () {
+ this.embedTextHtml.setValue( '' );
+ this.embedTextWikitext.setValue( '' );
+
+ this.embedSizeSwitchHtml.getMenu().toggle( false );
+ this.embedSizeSwitchWikitext.getMenu().toggle( false );
+ };
+
+ /**
+ * Selects the text in the current textbox by triggering a focus event.
+ */
+ EP.select = function () {
+ this.$currentMainEmbedText.focus();
+ };
+
+ /**
+ * 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
+ */
+ EP.getPossibleImageSizesForWikitext = function ( width, height ) {
+ var i, bucketName,
+ bucketWidth,
+ buckets = {
+ small: 300,
+ medium: 400,
+ large: 500
+ },
+ sizes = {},
+ bucketNames = Object.keys( buckets ),
+ widthToHeight = height / width;
+
+ for ( i = 0; i < bucketNames.length; i++ ) {
+ bucketName = bucketNames[ i ];
+ bucketWidth = buckets[ bucketName ];
+
+ if ( width > bucketWidth ) {
+ sizes[ bucketName ] = {
+ width: bucketWidth,
+ height: Math.round( bucketWidth * widthToHeight )
+ };
+ }
+ }
+
+ sizes.default = { width: null, height: null };
+
+ return sizes;
+ };
+
+ mw.mmv.ui.reuse.Embed = Embed;
+}( mediaWiki, jQuery, OO ) );