r111556 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r111555‎ | r111556 | r111557 >
Date:16:46, 15 February 2012
Author:nikerabbit
Status:ok (Comments)
Tags:i18nreview 
Comment:
Committing my work in embedded translation editor.
* Only exposed when &translate-beta=1 is provided in the URL, or when double clicking messages
* Please test functionally, feedback on the UI also welcome
* The dialog editor should not be affected, other than translation suggestions are now loaded synchronously
Modified paths:
  • /trunk/extensions/Translate/resources/ext.translate.quickedit.css (modified) (history)
  • /trunk/extensions/Translate/resources/ext.translate.quickedit.js (modified) (history)
  • /trunk/extensions/Translate/utils/MessageTable.php (modified) (history)
  • /trunk/extensions/Translate/utils/TranslationEditPage.php (modified) (history)

Diff [purge]

Index: trunk/extensions/Translate/utils/MessageTable.php
@@ -145,6 +145,11 @@
146146 $extra = '<br />' . $optional;
147147 }
148148
 149+ $tqeData = array(
 150+ 'data-title' => $title->getPrefixedText(),
 151+ 'data-group' => $this->group->getId(),
 152+ );
 153+
149154 $leftColumn = $this->getReviewButton( $m ) . $anchor . $tools['edit'] . $extra . $this->getReviewStatus( $m );
150155
151156 if ( $this->reviewMode && $original !== $message ) {
@@ -154,11 +159,11 @@
155160 TranslateUtils::convertWhiteSpaceToHTML( $original ) )
156161 );
157162
158 - $output .= Xml::tags( 'tr', array( 'class' => 'new' ),
 163+ $output .= Xml::tags( 'tr', array( 'class' => 'new tqe-inlineeditable' ) + $tqeData,
159164 Xml::tags( 'td', $rclasses, TranslateUtils::convertWhiteSpaceToHTML( $message ) )
160165 );
161166 } else {
162 - $output .= Xml::tags( 'tr', array( 'class' => 'def' ),
 167+ $output .= Xml::tags( 'tr', array( 'class' => 'def tqe-inlineeditable' ) + $tqeData,
163168 Xml::tags( 'td', null, $leftColumn ) .
164169 Xml::tags( 'td', $rclasses, TranslateUtils::convertWhiteSpaceToHTML( $message ) )
165170 );
Index: trunk/extensions/Translate/utils/TranslationEditPage.php
@@ -187,15 +187,23 @@
188188 * @return \array
189189 */
190190 public static function jsEdit( Title $title, $group = "" ) {
191 - global $wgUser;
 191+ global $wgUser, $wgRequest;
192192
193193 if ( !$wgUser->getOption( 'translate-jsedit' ) ) {
194194 return array();
195195 }
196196
 197+ if ( $wgRequest->getVal( 'translate-beta' ) ) {
 198+ $onclick = 'jQuery( this ).closest( ".inlineeditable" ).dblclick(); return false;';
 199+ } else {
 200+ $onclick = Xml::encodeJsCall(
 201+ 'return mw.translate.openDialog', array( $title->getPrefixedDbKey(), $group )
 202+ );
 203+ }
 204+
 205+
197206 return array(
198 - 'onclick' => Xml::encodeJsCall(
199 - 'return mw.translate.openDialog', array( $title->getPrefixedDbKey(), $group ) ),
 207+ 'onclick' => $onclick,
200208 'title' => wfMsg( 'translate-edit-title', $title->getPrefixedText() )
201209 );
202210 }
Index: trunk/extensions/Translate/resources/ext.translate.quickedit.js
@@ -21,7 +21,8 @@
2222 (function ( $, mw, undefined ) {
2323 "use strict";
2424 var dialogwidth = false,
25 - translate;
 25+ translate,
 26+ preloads = {};
2627
2728 function MessageCheckUpdater( callback ) {
2829 this.act = function() {
@@ -68,23 +69,28 @@
6970 }
7071 }
7172
72 - function registerFeatures( dialog, form, page, group ) {
 73+ function registerFeatures( callbacks, form, page, group ) {
7374 // Enable the collapsible element
7475 var $identical = $( '.mw-identical-title' );
7576 if ( $.isFunction( $identical.makeCollapsible ) ) {
7677 $identical.makeCollapsible();
7778 }
7879
79 - if ( mw.config.get( 'trlKeys' ) ) {
80 - form.find( '.mw-translate-next' ).click( function() {
81 - mw.translate.openNext( page, group );
82 - } );
83 -
84 - form.find( '.mw-translate-skip' ).click( function() {
85 - mw.translate.openNext( page, group );
86 - dialog.dialog( 'close' );
87 - return false;
88 - } );
 80+ if ( mw.config.get( 'trlKeys' ) || $( '.tqe-inlineeditable' ).length ) {
 81+ if ( callbacks.next === undefined ) {
 82+ form.find( '.mw-translate-next, .mw-translate-skip' ).attr( 'disabled', 'disabled' )
 83+ } else {
 84+ form.find( '.mw-translate-next' ).click( function () {
 85+ callbacks.next && callbacks.next();
 86+ } );
 87+ form.find( '.mw-translate-skip,' ).click( function () {
 88+ callbacks.close && callbacks.close();
 89+ callbacks.next && callbacks.next();
 90+ } );
 91+ form.find( '.mw-translate-close' ).click( function () {
 92+ callbacks.close && callbacks.close();
 93+ } );
 94+ }
8995 } else {
9096 form.find( '.mw-translate-next, .mw-translate-skip' )
9197 .attr( 'disabled', 'disabled' )
@@ -92,7 +98,7 @@
9399 }
94100
95101 form.find( '.mw-translate-history' ).click( function() {
96 - window.open( mw.config.get( 'wgServer' ) + mw.config.get( 'wgScript' ) + '?action=history&title=' + form.find( 'input[name=title]' ).val() );
 102+ window.open( mw.util.wikiScript() + '?action=history&title=' + form.find( 'input[name=title]' ).val() );
97103 return false;
98104 } );
99105
@@ -101,9 +107,13 @@
102108 window.open( $(this).attr( 'data-load-url' ) );
103109 return false;
104110 } );
 111+
 112+ form.find( 'input, textarea' ).focus( function() {
 113+ addAccessKeys( form );
 114+ } );
105115
106116 form.find( 'input#summary' ).focus( function() {
107 - $(this).css( 'width', '85%' );
 117+ $( this ).css( 'width', '85%' );
108118 } );
109119
110120 var textarea = form.find( '.mw-translate-edit-area' );
@@ -126,18 +136,27 @@
127137
128138 translate = {
129139 init: function() {
130 - var height = $( window ).height() * 0.7;
131140 dialogwidth = $( window ).width() * 0.8;
132 - mw.util.addCSS( "/* Inserted by ext.translate.quickedit */\n" +
133 - ".mw-sp-translate-edit-fields {\n" +
134 - "\tmax-height: " + height + "px;\n" +
135 - "\toverflow: auto\n}\n"
136 - );
 141+ var $inlines = $( '.tqe-inlineeditable' );
 142+ $inlines.dblclick( mw.translate.inlineEditor );
 143+
 144+ var $first = $inlines.first();
 145+ if ( $first.length ) {
 146+ var title = $first.data( 'title' );
 147+ var group = $first.data( 'group' );
 148+ mw.translate.loadEditor( title, group, $.noop );
 149+ }
 150+
 151+ var prev = null;
 152+ $inlines.each( function() {
 153+ if ( prev ) {
 154+ prev.next = this;
 155+ }
 156+ prev = this;
 157+ } )
137158 },
138159
139160 openDialog: function( page, group ) {
140 - var url = mw.config.get( 'wgScript' ) + '?title=Special:Translate/editpage&suggestions=async&page=$1&loadgroup=$2';
141 - url = url.replace( '$1', encodeURIComponent( page ) ).replace( '$2', encodeURIComponent( group ) );
142161 var id = 'jsedit' + page.replace( /[^a-zA-Z0-9_]/g, '_' );
143162
144163 var dialog = $( '#' + id );
@@ -146,20 +165,59 @@
147166 dialog.dialog( 'open' );
148167 return false;
149168 }
 169+
 170+ var dialog = $( '<div>' ).attr( 'id', id ).appendTo( $( 'body' ) );
 171+
 172+ var callbacks = {}
 173+ callbacks.close = function () { dialog.dialog( 'close' ); };
 174+ callbacks.next = function () { mw.translate.openNext( page, group ); };
 175+ mw.translate.openEditor( dialog, page, group, callbacks );
150176
151 - $( '<div>' ).attr( 'id', id ).appendTo( $( 'body' ) );
152 - dialog = $( '#' + id );
 177+ dialog.dialog( {
 178+ bgiframe: true,
 179+ width: dialogwidth,
 180+ title: page,
 181+ position: 'top',
 182+ resize: function() { $( '#' + id + ' textarea' ).width( '100%' ); },
 183+ resizeStop: function() { dialogwidth = $( '#' + id ).width(); },
 184+ } );
153185
 186+ return false;
 187+ },
 188+
 189+ loadEditor: function( page, group, callback ) {
 190+ // Try if it has been cached
 191+ var id = 'preload-' + page.replace( /[^a-zA-Z0-9_]/g, '_' );
 192+ var preload = preloads[id];
 193+ if ( preload !== undefined ) {
 194+ callback.call( preload );
 195+ delete preloads[id];
 196+ return;
 197+ }
 198+
 199+ var url = mw.util.wikiScript();
 200+ var params = {
 201+ title: 'Special:Translate/editpage',
 202+ suggestions: 'sync',
 203+ page: page,
 204+ loadgroup: group
 205+ };
 206+ $.get( url, params, function ( data ) {
 207+ preloads[id] = data;
 208+ callback.call( data );
 209+ } );
 210+ },
 211+
 212+ openEditor: function( element, page, group, callbacks ) {
 213+ var $target = $( element );
154214 var spinner = $( '<div>' ).attr( 'class', 'mw-ajax-loader' );
155 - dialog.html( $( '<div>' ).attr( 'class', 'mw-ajax-dialog' ).html( spinner ) );
 215+ $target.html( $( '<div>' ).attr( 'class', 'mw-ajax-dialog' ).html( spinner ) );
156216
157 - dialog.load( url, false, function() {
158 - var form = $( '#' + id + ' form' );
159 -
160 - registerFeatures( dialog, form, page, group );
161 - addAccessKeys( form );
162 - form.hide().slideDown();
163 -
 217+ mw.translate.loadEditor( page, group, function() {
 218+ $target.html( this );
 219+ callbacks.load && callbacks.load( $target );
 220+ var form = $target.find( 'form' );
 221+ registerFeatures( callbacks, form, page, group );
164222 form.ajaxForm( {
165223 dataType: 'json',
166224 success: function(json) {
@@ -172,26 +230,14 @@
173231 } else if ( json.edit.result === 'Failure' ) {
174232 alert( mw.msg( 'translate-js-save-failed' ) );
175233 } else if ( json.edit.result === 'Success' ) {
176 - dialog.dialog( 'close' );
 234+ callbacks.close && callbacks.close();
 235+ callbacks.success && callbacks.success( form.find( '.mw-translate-edit-area' ).val() );
177236 } else {
178237 alert( mw.msg( 'translate-js-save-failed' ) );
179238 }
180239 }
181240 } );
182241 } );
183 -
184 - dialog.dialog( {
185 - bgiframe: true,
186 - width: dialogwidth,
187 - title: page,
188 - position: 'top',
189 - resize: function() { $( '#' + id + ' textarea' ).width( '100%' ); },
190 - resizeStop: function() { dialogwidth = $( '#' + id ).width(); },
191 - focus: function() { addAccessKeys( dialog ); },
192 - close: function() { addAccessKeys( $([]) ); }
193 - } );
194 -
195 - return false;
196242 },
197243
198244 openNext: function( title, group ) {
@@ -212,6 +258,55 @@
213259 }
214260 alert( mw.msg( 'translate-js-nonext' ) );
215261 return;
 262+ },
 263+
 264+ inlineEditor: function () {
 265+ var $this = $( this );
 266+ if ( $this.hasClass( 'tqe-editor-loaded' ) ) {
 267+ // Editor is open, do not replace it
 268+ return;
 269+ }
 270+
 271+ var current = $this.html();
 272+ var $target = $( '<td>' ).attr( { colspan: 2 } );
 273+ $this.html( $target );
 274+ $this.addClass( 'tqe-editor-loaded' );
 275+
 276+ var classes = $this.attr( 'class' );
 277+ var page = $this.data( 'title' );
 278+ var group = $this.data( 'group' );
 279+ var next = $( this.next );
 280+ var callbacks = {}
 281+ callbacks.success = function ( text ) {
 282+ // Update the cell value with the new translation
 283+ $this.find( 'td' ).last().text( text );
 284+ };
 285+ callbacks.close = function () {
 286+ $this.html( current );
 287+ $this.removeClass( 'tqe-editor-loaded' );
 288+ };
 289+ callbacks.load = function ( editor ) {
 290+ var $header = $( '<div class="tqe-fakeheader"></div>' );
 291+ $header.text( page );
 292+ $header.append( '<input type=button class="mw-translate-close" value="X" />' );
 293+
 294+ $( editor ).find( 'form' ).prepend( $header );
 295+ };
 296+ if ( next.length ) {
 297+ callbacks.next = function () { next.dblclick(); };
 298+ // Preload the next item
 299+ var ntitle = next.data( 'title' );
 300+ var ngroup = next.data( 'group' );
 301+ mw.translate.loadEditor( ntitle, ngroup, $.noop );
 302+ }
 303+ mw.translate.openEditor( $target, page, group, callbacks );
 304+
 305+ // Remove any text selection caused by double clicking
 306+ var sel = window.getSelection ? window.getSelection() : document.selection;
 307+ if ( sel ) {
 308+ sel.removeAllRanges && sel.removeAllRanges();
 309+ sel.empty && sel.empty();
 310+ }
216311 }
217312 };
218313
Index: trunk/extensions/Translate/resources/ext.translate.quickedit.css
@@ -7,6 +7,12 @@
88 font-size: small;
99 }
1010
 11+.tqe-inlineeditable .mw-ajax-dialog {
 12+ margin: 5px;
 13+ margin-top: 15px;
 14+ margin-bottom: 15px;
 15+}
 16+
1117 .mw-sp-translate-edit-fields a {
1218 color: blue;
1319 }
@@ -94,3 +100,14 @@
95101 .mw-sp-translate-latestchange {
96102 padding-bottom: 0px;
97103 }
 104+
 105+
 106+.tqe-fakeheader {
 107+ border: 1px solid #CCC;
 108+ padding: .75em;
 109+ font-weight: bold;
 110+}
 111+
 112+.mw-translate-close {
 113+ float: right;
 114+}

Follow-up revisions

RevisionCommit summaryAuthorDate
r111999Close button did not work for the embedded editor for the last item in the ta...nikerabbit10:22, 21 February 2012

Comments

#Comment by Siebrand (talk | contribs)   09:26, 16 February 2012

Review comments:

#Comment by Nikerabbit (talk | contribs)   19:44, 22 February 2012

All have been fixed in follow ups.

Status & tagging log