Kranitor #004: MediaWiki-specific clean up and minor fixes

* Default value of wgVisualEditorParsoidURL is broken.
  Slash is needed, else Api will request to
  http://hostnamePageName
  Roan says double slashes are okay, and look cleaner than string
  search checks etc.

* Use .clone() for mw.Uri instead of converting to string
  and letting mw.Uri parse it, again. Clone creates a basic
  instance and copies over properties internally (deep copy,
  no references).

* No need for hasOwnProperty (and its potential issues)

* Code clean up
 - Whitespace consistency
 - Variable hosting
 - Remove redundant `return false;` statements in event handlers
   e.preventDefault() is a jQuery.Event method that takes care
   of cross-browser issues.
 - Same for e.keyCode||e.which thing, this is already normalized
   by jQuery.Event
 - Add missing parameter to setTimeout
 - Consistent order in success/error handlers in $.ajax options

Change-Id: I5bc24e0cbdf01b3704d4ccb0b45b3052e3b58694
This commit is contained in:
Timo Tijhof 2012-07-31 17:49:04 -07:00
parent 13ccb68ae1
commit c889292adf
4 changed files with 61 additions and 56 deletions

View file

@ -21,7 +21,9 @@ class ApiVisualEditor extends ApiBase {
if ( $params['paction'] === 'parse' ) {
if ( $page->exists() ) {
$parsed = Http::get(
$parsoid . $page->getPrefixedDBkey()
// Insert slash since wgVisualEditorParsoidURL may or may not
// end in a slash. Double slashes are no problem --catrope
$parsoid . '/' . $page->getPrefixedDBkey()
);
if ( $parsed ) {
@ -35,7 +37,10 @@ class ApiVisualEditor extends ApiBase {
);
}
} else {
$result = array( 'result' => 'success', 'parsed' => '' );
$result = array(
'result' => 'success',
'parsed' => ''
);
}
} elseif ( $params['paction'] === 'save' && $user->isBlocked() ) {
$result = array( 'result' => 'error' );

View file

@ -38,15 +38,19 @@ ve.init.mw.ViewPageTarget = function () {
this.deactivating = false;
this.scrollTop = null;
this.proxiedOnSurfaceModelTransact = ve.proxy( this.onSurfaceModelTransact, this );
this.surfaceOptions = { 'toolbars': { 'top': { 'float': !this.isMobileDevice } } };
this.surfaceOptions = {
'toolbars': {
'top': {
'float': !this.isMobileDevice
}
}
};
this.currentUri = new mw.Uri( window.location.toString() );
this.section = this.currentUri.query.vesection || null;
this.namespaceName = mw.config.get( 'wgCanonicalNamespace' );
this.viewUri = new mw.Uri( mw.util.wikiGetlink( this.pageName ) );
this.editUri = new mw.Uri( this.viewUri.toString() );
this.editUri.extend( { 'action': 'edit' } );
this.veEditUri = new mw.Uri( this.viewUri.toString() );
this.veEditUri.extend( { 'veaction': 'edit' } );
this.editUri = this.viewUri.clone().extend( { 'action': 'edit' } );
this.veEditUri = this.viewUri.clone().extend( { 'veaction': 'edit' } );
this.isViewPage = (
this.namespaceName === 'VisualEditor' &&
mw.config.get( 'wgAction' ) === 'view' &&
@ -54,7 +58,7 @@ ve.init.mw.ViewPageTarget = function () {
);
this.canBeActivated = (
this.namespaceName === 'VisualEditor' ||
this.pageName.substr( 0, 13 ) === 'VisualEditor:'
this.pageName.indexOf( 'VisualEditor:' ) === 0
);
// Events
@ -96,7 +100,7 @@ ve.init.mw.ViewPageTarget.saveDialogTemplate = '\
id="ve-init-mw-viewPageTarget-saveDialog-minorEdit">\
<label class="ve-init-mw-viewPageTarget-saveDialog-minorEdit-label" \
for="ve-init-mw-viewPageTarget-saveDialog-minorEdit"></label>\
<div style="clear:both"></div>\
<div style="clear: both;"></div>\
<input type="checkbox" name="watchList" \
id="ve-init-mw-viewPageTarget-saveDialog-watchList">\
<label class="ve-init-mw-viewPageTarget-saveDialog-watchList-label" \
@ -106,7 +110,7 @@ ve.init.mw.ViewPageTarget.saveDialogTemplate = '\
<span class="ve-init-mw-viewPageTarget-saveDialog-saveButton-label"></span>\
<div class="ve-init-mw-viewPageTarget-saveDialog-saveButton-icon"></div>\
</button>\
<div style="clear:both"></div>\
<div style="clear: both;"></div>\
</div>\
<div class="ve-init-mw-viewPageTarget-saveDialog-foot">\
<p class="ve-init-mw-viewPageTarget-saveDialog-license"></p>\
@ -215,13 +219,15 @@ ve.init.mw.ViewPageTarget.prototype.onSave = function ( html ) {
} else {
// Update watch link to match 'watch checkbox' in save dialog.
// User logged in if module loaded.
if ( mw.page.hasOwnProperty( 'watch' ) ) {
var watchPage = this.$saveDialog
// Just checking for mw.page.watch is not enough because in Firefox
// there is Object.prototype.watch...
if ( mw.page.watch && mw.page.watch.updateWatchLink ) {
var watchChecked = this.$saveDialog
.find( '#ve-init-mw-viewPageTarget-saveDialog-watchList')
.prop( 'checked' );
mw.page.watch.updateWatchLink(
$('#ca-watch a, #ca-unwatch a'),
watchPage === true ? 'unwatch': 'watch'
$( '#ca-watch a, #ca-unwatch a' ),
watchChecked ? 'unwatch': 'watch'
);
}
this.hideSaveDialog();
@ -241,7 +247,7 @@ ve.init.mw.ViewPageTarget.prototype.onSave = function ( html ) {
* @param {Mixed} error Thrown exception or HTTP error string
*/
ve.init.mw.ViewPageTarget.prototype.onSaveError = function ( response, status, error ) {
// XXX: Don't use alert.
// TODO: Don't use alert.
alert( ve.msg( 'visualeditor-saveerror', status ) );
};
@ -255,7 +261,6 @@ ve.init.mw.ViewPageTarget.prototype.onEditTabClick = function ( e ) {
this.activate();
// Prevent the edit tab's normal behavior
e.preventDefault();
return false;
};
/**
@ -269,7 +274,6 @@ ve.init.mw.ViewPageTarget.prototype.onEditSectionLinkClick = function ( e ) {
this.activate();
// Prevent the edit tab's normal behavior
e.preventDefault();
return false;
};
/**
@ -283,7 +287,6 @@ ve.init.mw.ViewPageTarget.prototype.onViewTabClick = function ( e ) {
this.deactivate();
// Prevent the edit tab's normal behavior
e.preventDefault();
return false;
}
};
@ -399,7 +402,7 @@ ve.init.mw.ViewPageTarget.prototype.setupSkinTabs = function () {
// Only sysop users will have an edit tab in this namespace, so we might need to add one
if ( $( '#ca-edit' ).length === 0 ) {
// Add edit tab
action = Number( mw.config.get( 'wgArticleId', 0 ) ) === 0 ? 'create' : 'edit';
action = mw.config.get( 'wgArticleId', 0 ) === 0 ? 'create' : 'edit';
mw.util.addPortletLink(
'p-views',
@ -464,7 +467,6 @@ ve.init.mw.ViewPageTarget.prototype.setupSectionEditLinks = function () {
$links.click( ve.proxy( this.onEditSectionLinkClick, this ) );
} else {
$links.each( function () {
// FIXME: mw.Uri is mediaWiki specific
var veSectionEditUri = new mw.Uri( veEditUri.toString() ),
sectionEditUri = new mw.Uri( $(this).attr( 'href' ) );
veSectionEditUri.extend( { 'vesection': sectionEditUri.query.section } );
@ -489,12 +491,10 @@ ve.init.mw.ViewPageTarget.prototype.setupToolbarSaveButton = function () {
'mousedown': function ( e ) {
$(this).addClass( 've-init-mw-viewPageTarget-toolbar-saveButton-down' );
e.preventDefault();
return false;
},
'mouseleave mouseup': function ( e ) {
$(this).removeClass( 've-init-mw-viewPageTarget-toolbar-saveButton-down' );
e.preventDefault();
return false;
},
'click': ve.proxy( this.onToolbarSaveButtonClick, this )
} );
@ -539,7 +539,7 @@ ve.init.mw.ViewPageTarget.prototype.setupSaveDialog = function () {
.text( ve.msg( 'summary' ) )
.end()
.find( '#ve-init-mw-viewPageTarget-saveDialog-editSummary' )
.on( 'keydown', function( e ) {
.on( 'keydown', function ( e ) {
if ( e.which === 13 ) {
viewPage.onSaveDialogSaveButtonClick();
}
@ -663,7 +663,7 @@ ve.init.mw.ViewPageTarget.prototype.hideSpinner = function () {
* @method
*/
ve.init.mw.ViewPageTarget.prototype.showPageContent = function () {
$( '#bodyContent >.ve-init-mw-viewPageTarget-content' )
$( '#bodyContent > .ve-init-mw-viewPageTarget-content' )
.removeClass( 've-init-mw-viewPageTarget-content' )
.show()
.fadeTo( 0, 1 );
@ -675,7 +675,7 @@ ve.init.mw.ViewPageTarget.prototype.showPageContent = function () {
* @method
*/
ve.init.mw.ViewPageTarget.prototype.mutePageContent = function () {
$( '#bodyContent >:visible:not(#siteSub)' )
$( '#bodyContent > :visible:not(#siteSub)' )
.addClass( 've-init-mw-viewPageTarget-content' )
.fadeTo( 'fast', 0.6 );
};
@ -686,7 +686,7 @@ ve.init.mw.ViewPageTarget.prototype.mutePageContent = function () {
* @method
*/
ve.init.mw.ViewPageTarget.prototype.hidePageContent = function () {
$( '#bodyContent >:visible:not(#siteSub)' )
$( '#bodyContent > :visible:not(#siteSub)' )
.addClass( 've-init-mw-viewPageTarget-content' )
.hide();
};
@ -719,10 +719,9 @@ ve.init.mw.ViewPageTarget.prototype.hideTableOfContents = function () {
ve.init.mw.ViewPageTarget.prototype.showSaveDialog = function () {
var viewPage = this;
this.unlockSaveDialogSaveButton();
this.$saveDialog.fadeIn( 'fast' ).find( 'input:first' ).focus();
$( document ).on( 'keydown', function( e ) {
var key = e.keyCode || e.which;
if ( key === 27 ) {
this.$saveDialog.fadeIn( 'fast' ).find( 'input' ).eq( 0 ).focus();
$( document ).on( 'keydown', function ( e ) {
if ( e.which === 27 ) {
viewPage.onSaveDialogCloseButtonClick();
}
});
@ -759,7 +758,8 @@ ve.init.mw.ViewPageTarget.prototype.resetSaveDialog = function () {
* @method
*/
ve.init.mw.ViewPageTarget.prototype.enableToolbarSaveButton = function () {
this.$toolbarSaveButton.removeClass( 've-init-mw-viewPageTarget-toolbar-saveButton-disabled' );
this.$toolbarSaveButton
.removeClass( 've-init-mw-viewPageTarget-toolbar-saveButton-disabled' );
};
/**
@ -768,7 +768,8 @@ ve.init.mw.ViewPageTarget.prototype.enableToolbarSaveButton = function () {
* @method
*/
ve.init.mw.ViewPageTarget.prototype.disableToolbarSaveButton = function () {
this.$toolbarSaveButton.addClass( 've-init-mw-viewPageTarget-toolbar-saveButton-disabled' );
this.$toolbarSaveButton
.addClass( 've-init-mw-viewPageTarget-toolbar-saveButton-disabled' );
};
/**
@ -787,7 +788,8 @@ ve.init.mw.ViewPageTarget.prototype.unlockSaveDialogSaveButton = function () {
* @method
*/
ve.init.mw.ViewPageTarget.prototype.lockSaveDialogSaveButton = function () {
this.$saveDialogSaveButton.addClass( 've-init-mw-viewPageTarget-saveDialog-saveButton-saving' );
this.$saveDialogSaveButton
.addClass( 've-init-mw-viewPageTarget-saveDialog-saveButton-saving' );
};
/**
@ -798,8 +800,7 @@ ve.init.mw.ViewPageTarget.prototype.lockSaveDialogSaveButton = function () {
* @method
*/
ve.init.mw.ViewPageTarget.prototype.attachToolbar = function () {
this.$toolbarWrapper = this.$surface.find( '.es-toolbar-wrapper' );
this.$toolbarWrapper
this.$toolbarWrapper = this.$surface.find( '.es-toolbar-wrapper' )
.insertBefore( $( '#firstHeading' ) )
.find( '.es-toolbar' )
.slideDown( 'fast' );
@ -1038,8 +1039,7 @@ ve.init.mw.ViewPageTarget.prototype.onBeforeUnload = function () {
// ...but if the user chooses not to leave the page, we need to rebind it
setTimeout( function () {
window.onbeforeunload = proxiedOnBeforeUnload;
// XXX: Missing argument to setTimeout?
} );
}, 1 );
return message;
}
};

View file

@ -14,7 +14,7 @@
* @constructor
* @param {String} pageName Name of target page
*/
ve.init.mw.Platform = function() {
ve.init.mw.Platform = function () {
// Inheritance
ve.init.Platform.call( this );
@ -28,12 +28,12 @@ ve.init.mw.Platform = function() {
/**
* Gets a regular expression that matches allowed external link URLs.
*
* Uses MediaWiki's {wgUrlProtocols} variable.
* Uses the mw.config wgUrlProtocols variable.
*
* @method
* @returns {RegExp} Regular expression object
*/
ve.init.mw.Platform.prototype.getExternalLinkUrlProtocolsRegExp = function() {
ve.init.mw.Platform.prototype.getExternalLinkUrlProtocolsRegExp = function () {
return this.externalLinkUrlProtocolsRegExp;
};
@ -45,7 +45,7 @@ ve.init.mw.Platform.prototype.getExternalLinkUrlProtocolsRegExp = function() {
* @method
* @returns {String} Remote modules URL
*/
ve.init.mw.Platform.prototype.getModulesUrl = function() {
ve.init.mw.Platform.prototype.getModulesUrl = function () {
return this.modulesUrl;
};
@ -57,7 +57,7 @@ ve.init.mw.Platform.prototype.getModulesUrl = function() {
* @method
* @param {Object} messages Map of message-key/message-string pairs
*/
ve.init.mw.Platform.prototype.addMessages = function( messages ) {
ve.init.mw.Platform.prototype.addMessages = function ( messages ) {
return mw.messages.set( messages );
};
@ -71,7 +71,7 @@ ve.init.mw.Platform.prototype.addMessages = function( messages ) {
* @param {Mixed} [...] List of arguments which will be injected at $1, $2, etc. in the messaage
* @returns {String} Localized message
*/
ve.init.mw.Platform.prototype.getMessage = function( key ) {
ve.init.mw.Platform.prototype.getMessage = function ( key ) {
return mw.msg.apply( mw.msg, arguments );
};

View file

@ -14,7 +14,7 @@
* @constructor
* @param {String} pageName Name of target page
*/
ve.init.mw.Target = function( pageName ) {
ve.init.mw.Target = function ( pageName ) {
// Inheritance
ve.EventEmitter.call( this );
@ -47,7 +47,7 @@ ve.init.mw.Target = function( pageName ) {
* @param {String} status Text status message
* @emits loadError (null, message, null)
*/
ve.init.mw.Target.onLoad = function( response, status ) {
ve.init.mw.Target.onLoad = function ( response, status ) {
var data = response['ve-parsoid'];
if ( !data ) {
this.loading = false;
@ -59,7 +59,7 @@ ve.init.mw.Target.onLoad = function( response, status ) {
this.loading = false;
this.emit( 'loadError', null, 'No HTML content in response from server', null );
} else {
this.dom = $( '<div></div>' ).html( data.parsed )[0];
this.dom = $( '<div>' ).html( data.parsed )[0];
// Everything worked, the page was loaded, continue as soon as the module is ready
mw.loader.using( this.modules, ve.proxy( ve.init.mw.Target.onReady, this ) );
}
@ -75,7 +75,7 @@ ve.init.mw.Target.onLoad = function( response, status ) {
* @method
* @emits load (dom)
*/
ve.init.mw.Target.onReady = function() {
ve.init.mw.Target.onReady = function () {
this.loading = false;
this.emit( 'load', this.dom );
// Release DOM data
@ -94,7 +94,7 @@ ve.init.mw.Target.onReady = function() {
* @param {Mixed} error Thrown exception or HTTP error string
* @emits loadError (response, text, exception)
*/
ve.init.mw.Target.onLoadError = function( response, text, exception ) {
ve.init.mw.Target.onLoadError = function ( response, text, exception ) {
this.loading = false;
this.emit( 'loadError', response, text, exception );
};
@ -111,7 +111,7 @@ ve.init.mw.Target.onLoadError = function( response, text, exception ) {
* @emits save (html)
* @emits saveError (null, message, null)
*/
ve.init.mw.Target.onSave = function( response, status ) {
ve.init.mw.Target.onSave = function ( response, status ) {
this.saving = false;
var data = response['ve-parsoid'];
if ( !data ) {
@ -137,7 +137,7 @@ ve.init.mw.Target.onSave = function( response, status ) {
* @param {Mixed} error Thrown exception or HTTP error string
* @emits saveError (response, status, error)
*/
ve.init.mw.Target.onSaveError = function( response, status, error ) {
ve.init.mw.Target.onSaveError = function ( response, status, error ) {
this.saving = false;
this.emit( 'saveError', response, status, error );
};
@ -160,7 +160,7 @@ ve.init.mw.Target.onSaveError = function( response, status, error ) {
* @param {Function} callback Function to call when complete, accepts error and dom arguments
* @returns {Boolean} Loading is now in progress
*/
ve.init.mw.Target.prototype.load = function( callback ) {
ve.init.mw.Target.prototype.load = function ( callback ) {
// Prevent duplicate requests
if ( this.loading ) {
return false;
@ -182,8 +182,8 @@ ve.init.mw.Target.prototype.load = function( callback ) {
// Wait up to 10 seconds before giving up
'timeout': 10000,
'cache': 'false',
'error': ve.proxy( ve.init.mw.Target.onLoadError, this ),
'success': ve.proxy( ve.init.mw.Target.onLoad, this )
'success': ve.proxy( ve.init.mw.Target.onLoad, this ),
'error': ve.proxy( ve.init.mw.Target.onLoadError, this )
} );
return true;
};
@ -211,7 +211,7 @@ ve.init.mw.Target.prototype.load = function( callback ) {
* @param {Function} callback Function to call when complete, accepts error and html arguments
* @returns {Boolean} Saving is now in progress
*/
ve.init.mw.Target.prototype.save = function( dom, options, callback ) {
ve.init.mw.Target.prototype.save = function ( dom, options, callback ) {
// Prevent duplicate requests
if ( this.saving ) {
return false;
@ -235,8 +235,8 @@ ve.init.mw.Target.prototype.save = function( dom, options, callback ) {
'type': 'POST',
// Wait up to 10 seconds before giving up
'timeout': 10000,
'error': ve.proxy( ve.init.mw.Target.onSaveError, this ),
'success': ve.proxy( ve.init.mw.Target.onSave, this )
'success': ve.proxy( ve.init.mw.Target.onSave, this ),
'error': ve.proxy( ve.init.mw.Target.onSaveError, this )
} );
return true;
};