From 40a6980d28f2a6beb5e9204c250e2cd6cb637bfe Mon Sep 17 00:00:00 2001 From: Aaron Arcos Date: Wed, 19 Mar 2014 15:35:55 -0700 Subject: [PATCH] Fix some text selection issues with share/embed Change-Id: Ic9d330c04d4e9335cdfce6e99870d1e5877b2a90 Mingle: https://wikimedia.mingle.thoughtworks.com/projects/multimedia/cards/374 --- MultimediaViewer.i18n.php | 2 ++ MultimediaViewer.php | 6 ++---- resources/mmv/ui/mmv.ui.reuse.embed.js | 13 +++++++++---- resources/mmv/ui/mmv.ui.reuse.share.js | 16 +++++++++++++++- tests/qunit/mmv/ui/mmv.ui.reuse.embed.test.js | 14 +++++++++++++- tests/qunit/mmv/ui/mmv.ui.reuse.share.test.js | 6 +++++- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/MultimediaViewer.i18n.php b/MultimediaViewer.i18n.php index 1012db866..b7faf06e3 100644 --- a/MultimediaViewer.i18n.php +++ b/MultimediaViewer.i18n.php @@ -82,6 +82,7 @@ $messages['en'] = array( 'multimediaviewer-fileusage-global-section' => 'On other sites', 'multimediaviewer-reuse-link' => 'Use this file', + 'multimediaviewer-reuse-loading-placeholder' => 'Loading…', 'multimediaviewer-share-tab' => 'Share', 'multimediaviewer-embed-tab' => 'Embed', @@ -247,6 +248,7 @@ Followed by {{msg-mw|Multimediaviewer-fileusage-link}} and the list of pages. See also: * {{msg-mw|Multimediaviewer-fileusage-local-section}}', 'multimediaviewer-reuse-link' => 'Text of the link on the metadata panel which opens the reuse panel', + 'multimediaviewer-reuse-loading-placeholder' => 'Text that appears in all reuse text boxes as a placeholder while the data loads', 'multimediaviewer-share-tab' => 'Tab title text for the file reuse panel - used for the section with shareable URLs.', 'multimediaviewer-embed-tab' => 'Tab title text for the file reuse panel - used for the section with embeddable HTML and wikitext.', 'multimediaviewer-link-to-page' => 'Used as alt-text to describe a URL that goes to a File: page for an image.', diff --git a/MultimediaViewer.php b/MultimediaViewer.php index bf6470166..0b86aa556 100644 --- a/MultimediaViewer.php +++ b/MultimediaViewer.php @@ -423,10 +423,6 @@ call_user_func( function() { 'mmv.ui', 'oojs', ), - - 'messages' => array( - 'multimediaviewer-reuse-link', - ), ), $moduleInfo( 'mmv/ui' ) ); $wgResourceModules['mmv.ui.reuse.share'] = array_merge( array( @@ -445,6 +441,7 @@ call_user_func( function() { ), 'messages' => array( + 'multimediaviewer-reuse-loading-placeholder', 'multimediaviewer-share-tab', 'multimediaviewer-link-to-file', @@ -470,6 +467,7 @@ call_user_func( function() { ), 'messages' => array( + 'multimediaviewer-reuse-loading-placeholder', 'multimediaviewer-embed-tab', 'multimediaviewer-embed-html', 'multimediaviewer-embed-wt', diff --git a/resources/mmv/ui/mmv.ui.reuse.embed.js b/resources/mmv/ui/mmv.ui.reuse.embed.js index 8d5f247cd..54013b5d2 100644 --- a/resources/mmv/ui/mmv.ui.reuse.embed.js +++ b/resources/mmv/ui/mmv.ui.reuse.embed.js @@ -79,12 +79,18 @@ readOnly: true } ); + this.embedTextHtml.$element.find( 'textarea' ) + .prop( 'placeholder', mw.message( 'multimediaviewer-reuse-loading-placeholder' ).text() ); + this.embedTextWikitext = new oo.ui.TextInputWidget( { classes: [ 'mw-mlb-embed-text-wt', 'active' ], multiline: true, readOnly: true } ); + this.embedTextWikitext.$element.find( 'textarea' ) + .prop( 'placeholder', mw.message( 'multimediaviewer-reuse-loading-placeholder' ).text() ); + $( '

' ) .append( this.embedTextHtml.$element, @@ -107,7 +113,6 @@ wikitextButtonOption = new oo.ui.ButtonOptionWidget( 'wt', { label: mw.message( 'multimediaviewer-embed-wt' ).text(), - selected: true } ); htmlButtonOption = new oo.ui.ButtonOptionWidget( 'html', { label: mw.message( 'multimediaviewer-embed-html' ).text() @@ -152,7 +157,6 @@ }, { label: mw.message( 'multimediaviewer-small-embed-size', 0, 0 ).text(), - selected: true } ), this.embedWtSizeChoices.medium = new oo.ui.MenuItemWidget( { @@ -191,7 +195,6 @@ }, { label: mw.message( 'multimediaviewer-small-embed-size', 0, 0 ).text(), - selected: true } ), this.embedHtmlSizeChoices.medium = new oo.ui.MenuItemWidget( { @@ -243,6 +246,7 @@ // Select all text once element gets focus this.embedTextHtml.onDOMEvent( 'focus', $.proxy( this.selectAllOnEvent, $htmlTextarea ) ); this.embedTextWikitext.onDOMEvent( 'focus', $.proxy( this.selectAllOnEvent, $wikitextTextarea ) ); + // Disable partial text selection inside the textboxes this.embedTextHtml.onDOMEvent( 'mousedown click', $.proxy( this.onlyFocus, $htmlTextarea ) ); this.embedTextWikitext.onDOMEvent( 'mousedown click', $.proxy( this.onlyFocus, $wikitextTextarea ) ); @@ -524,6 +528,7 @@ this.currentSizeMenu.selectItem( this.currentSizeMenu.getSelectedItem() ); this.getThumbnailUrlPromise().done( function ( thumbnail ) { embed.setThumbnailURL( thumbnail ); + embed.select(); } ); }; @@ -598,7 +603,7 @@ }; /** - * Selects the text in the current text box. + * Selects the text in the current textbox by triggering a focus event. */ EP.select = function () { this.$currentMainEmbedText.focus(); diff --git a/resources/mmv/ui/mmv.ui.reuse.share.js b/resources/mmv/ui/mmv.ui.reuse.share.js index 389171caa..43709c20a 100644 --- a/resources/mmv/ui/mmv.ui.reuse.share.js +++ b/resources/mmv/ui/mmv.ui.reuse.share.js @@ -42,6 +42,9 @@ readOnly: true } ); + this.pageInput.$element.find( 'input' ) + .prop( 'placeholder', mw.message( 'multimediaviewer-reuse-loading-placeholder' ).text() ); + this.$pageLink = $( '' ) .addClass( 'mw-mlb-share-page-link' ) .prop( 'alt', mw.message( 'multimediaviewer-link-to-page' ).text() ) @@ -59,7 +62,7 @@ */ SP.show = function () { this.constructor.super.prototype.show.call( this ); - this.pageInput.$element.focus(); + this.select(); }; /** @@ -70,6 +73,9 @@ // FIXME this should be handled by mmv.js to be DRY var url = image.descriptionUrl + '#mediaviewer/' + image.title.getMainText(); this.pageInput.setValue( url ); + + this.select(); + this.$pageLink.prop( 'href', url ); }; @@ -88,6 +94,7 @@ var $input = this.pageInput.$element.find( 'input' ); this.pageInput.onDOMEvent( 'focus', $.proxy( this.selectAllOnEvent, $input ) ); + // Disable partial text selection inside the textbox this.pageInput.onDOMEvent( 'mousedown click', $.proxy( this.onlyFocus, $input ) ); }; @@ -100,6 +107,13 @@ this.pageInput.offDOMEvent( 'focus mousedown click' ); }; + /** + * Selects the text in the readonly textbox by triggering a focus event. + */ + SP.select = function () { + this.pageInput.$element.focus(); + }; + mw.mmv.ui.reuse.Share = Share; }( mediaWiki, jQuery, OO ) ); diff --git a/tests/qunit/mmv/ui/mmv.ui.reuse.embed.test.js b/tests/qunit/mmv/ui/mmv.ui.reuse.embed.test.js index 891b9f4f4..3ad0121a6 100644 --- a/tests/qunit/mmv/ui/mmv.ui.reuse.embed.test.js +++ b/tests/qunit/mmv/ui/mmv.ui.reuse.embed.test.js @@ -225,7 +225,7 @@ } } ); - QUnit.test( 'set():', 4, function ( assert ) { + QUnit.test( 'set():', 6, function ( assert ) { var embed = new mw.mmv.ui.reuse.Embed( $qf ), title = mw.Title.newFromText( 'File:Foobar.jpg' ), src = 'https://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg', @@ -234,9 +234,21 @@ width = 15, height = 20; + QUnit.stop(); + embed.updateMenuOptions = function( sizes, options ) { assert.strictEqual( options.length, 4, 'Options passed correctly.' ); }; + embed.getThumbnailUrlPromise = function () { + return $.Deferred().resolve().promise(); + }; + embed.setThumbnailURL = function () { + assert.ok( true, 'setThumbnailURL() is called after data is collected.' ); + }; + embed.select = function () { + assert.ok( true, 'select() is called after data is collected.' ); + QUnit.start(); + }; assert.ok( !embed.embedFileInfo, 'embedFileInfo not set yet.' ); diff --git a/tests/qunit/mmv/ui/mmv.ui.reuse.share.test.js b/tests/qunit/mmv/ui/mmv.ui.reuse.share.test.js index 113f43f54..181291ac9 100644 --- a/tests/qunit/mmv/ui/mmv.ui.reuse.share.test.js +++ b/tests/qunit/mmv/ui/mmv.ui.reuse.share.test.js @@ -31,7 +31,7 @@ assert.ok( share.$pageLink, 'Link created.' ); } ); - QUnit.test( 'set()/empty():', 3, function ( assert ) { + QUnit.test( 'set()/empty():', 4, function ( assert ) { var share = makeShare(), image = { // fake mw.mmv.model.Image title: new mw.Title( 'File:Foobar.jpg' ), @@ -40,6 +40,10 @@ assert.notStrictEqual( ! share.pageInput.getValue(), '', 'pageInput is empty.' ); + share.select = function () { + assert.ok( true, 'Text has been selected after data is set.' ); + }; + share.set( image ); assert.notStrictEqual( share.pageInput.getValue(), '', 'pageInput is not empty.' );