[mediawiki.api] clean up
authorKrinkle <krinkle@users.mediawiki.org>
Wed, 21 Dec 2011 23:52:37 +0000 (23:52 +0000)
committerKrinkle <krinkle@users.mediawiki.org>
Wed, 21 Dec 2011 23:52:37 +0000 (23:52 +0000)
* Adding return values to most of the ajax functions so that the jqXHR object (originally returned by jQuery.ajax) is available. Some functions documented they already did this, some don't. Now they all do and are also documented as such.

* Renaming a few 'callback' arguments to 'success' to avoid confusion with 'error'.

* Removed unused variables
** mw.Api's instance this.url was unused
** var cachedToken was unused in mediawiki.api.titleblacklist.js

* Making closure argument order the same and referencing mediaWiki as a global (mw is something thought not to be a global but mediaWiki certainly is, no need to access window from the global scope and then the mediaWiki property of it). Also renamed any used of $j to $. Adding 'undefined' to the closure arguments where missing.

* Re-written the mw.Api constructor's logic for options. Now keeping a defaultOptions privately "statically" cached outside the constructor and using that to build the options object.

* Made all non-block comments the same comment style (some were /* */ or /* \n */)

* Completed parameter documentation and wrote TODO as @todo and added an example use for mw.Api in the documentation.

* Some other random whitespacing, line breaking, merged var statement, and moved them out of blocks (since JS doesn't have block scope) into the main function body for clarity. And some other random JS Lint/JS Hint stuff.

* Added comment to api.titleblacklist module about the module not being in core but in the TitleBlacklist extension.

resources/mediawiki/mediawiki.api.category.js
resources/mediawiki/mediawiki.api.edit.js
resources/mediawiki/mediawiki.api.js
resources/mediawiki/mediawiki.api.parse.js
resources/mediawiki/mediawiki.api.titleblacklist.js

index 269d852..c8c18e6 100644 (file)
@@ -1,46 +1,46 @@
-// library to assist with API calls on categories
+/**
+ * Additional mw.Api methods to assist with API calls related to categories.
+ */
 
-( function( mw, $ ) {
+( function( $, mw, undefined ) {
 
-       $.extend( mw.Api.prototype, { 
+       $.extend( mw.Api.prototype, {
                /**
-                * Determine if a category exists
-                * @param {mw.Title} 
-                * @param {Function} callback to pass boolean of category's existence
-                * @param {Function} optional callback to run if api error
+                * Determine if a category exists.
+                * @param title {mw.Title}
+                * @param success {Function} callback to pass boolean of category's existence
+                * @param err {Function} optional callback to run if api error
                 * @return ajax call object
                 */
-               isCategory: function( title, callback, err ) {
+               isCategory: function( title, success, err ) {
                        var params = {
-                               'prop': 'categoryinfo',
-                               'titles': title.toString()
-                       };
-
-                       var ok = function( data ) {
-                               var exists = false;
-                               if ( data.query && data.query.pages ) {
-                                       $.each( data.query.pages, function( id, page ) {
-                                               if ( page.categoryinfo ) {
-                                                       exists = true;
-                                               }
-                                       } );
-                               }
-                               callback( exists );
-                       };
+                                       prop: 'categoryinfo',
+                                       titles: title.toString()
+                               },
+                               ok = function( data ) {
+                                       var exists = false;
+                                       if ( data.query && data.query.pages ) {
+                                               $.each( data.query.pages, function( id, page ) {
+                                                       if ( page.categoryinfo ) {
+                                                               exists = true;
+                                                       }
+                                               } );
+                                       }
+                                       success( exists );
+                               };
 
                        return this.get( params, { ok: ok, err: err } );
-
                },
 
                /**
-                * Get a list of categories that match a certain prefix. 
+                * Get a list of categories that match a certain prefix.
                 *   e.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ...
-                * @param {String} prefix to match
-                * @param {Function} callback to pass matched categories to
-                * @param {Function} optional callback to run if api error
-                * @return ajax call object
+                * @param prefix {String} prefix to match
+                * @param success {Function} callback to pass matched categories to
+                * @param err {Function} optional callback to run if api error
+                * @return {jqXHR}
                 */
-               getCategoriesByPrefix: function( prefix, callback, err ) {              
+               getCategoriesByPrefix: function( prefix, success, err ) {
 
                        // fetch with allpages to only get categories that have a corresponding description page.
                        var params = {
 
                        var ok = function( data ) {
                                var texts = [];
-                               if ( data.query && data.query.allpages ) { 
+                               if ( data.query && data.query.allpages ) {
                                        $.each( data.query.allpages, function( i, category ) {
-                                               texts.push( new mw.Title( category.title ).getNameText() ); 
+                                               texts.push( new mw.Title( category.title ).getNameText() );
                                        } );
                                }
-                               callback( texts );
+                               success( texts );
                        };
 
                        return this.get( params, { ok: ok, err: err } );
-
                },
 
 
                /**
                 * Get the categories that a particular page on the wiki belongs to
-                * @param {mw.Title}
-                * @param {Function} callback to pass categories to (or false, if title not found)
-                * @param {Function} optional callback to run if api error
-                * @param {Boolean} optional asynchronousness (default = true = async)
-                * @return ajax call object 
+                * @param title {mw.Title}
+                * @param success {Function} callback to pass categories to (or false, if title not found)
+                * @param err {Function} optional callback to run if api error
+                * @param async {Boolean} optional asynchronousness (default = true = async)
+                * @return {jqXHR}
                 */
-               getCategories: function( title, callback, err, async ) {
-                       var params = {
+               getCategories: function( title, success, err, async ) {
+                       var params, ok;
+                       params = {
                                prop: 'categories',
                                titles: title.toString()
                        };
                        if ( async === undefined ) {
                                async = true;
                        }
-
-                       var ok = function( data ) {
+                       ok = function( data ) {
                                var ret = false;
                                if ( data.query && data.query.pages ) {
                                        $.each( data.query.pages, function( id, page ) {
                                                if ( page.categories ) {
-                                                       if ( typeof ret !== 'object' ) { 
+                                                       if ( typeof ret !== 'object' ) {
                                                                ret = [];
                                                        }
-                                                       $.each( page.categories, function( i, cat ) { 
-                                                               ret.push( new mw.Title( cat.title ) ); 
+                                                       $.each( page.categories, function( i, cat ) {
+                                                               ret.push( new mw.Title( cat.title ) );
                                                        } );
                                                }
                                        } );
                                }
-                               callback( ret );
+                               success( ret );
                        };
 
                        return this.get( params, { ok: ok, err: err, async: async } );
-
                }
 
        } );
-} )( window.mediaWiki, jQuery );
+
+} )( jQuery, mediaWiki );
index db8a6a3..58c43f9 100644 (file)
-// library to assist with edits
+/**
+ * Additional mw.Api methods to assist with API calls related to editing wiki pages.
+ */
 
-( function( mw, $, undefined ) {
+( function( $, mw, undefined ) {
 
-       // cached token so we don't have to keep fetching new ones for every single post
+       // Cache token so we don't have to keep fetching new ones for every single request.
        var cachedToken = null;
 
-       $.extend( mw.Api.prototype, { 
+       $.extend( mw.Api.prototype, {
 
-               /* Post to API with edit token. If we have no token, get one and try to post.
-                * If we have a cached token try using that, and if it fails, blank out the
-                * cached token and start over.
-                * 
-                * @param params API parameters
-                * @param ok callback for success
-                * @param err (optional) error callback
+               /**
+                * Post to API with edit token. If we have no token, get one and try to post.
+                * If we have a cached token try using that, and if it fails, blank out the
+                * cached token and start over.
+                *
+                * @param params {Object} API parameters
+                * @param ok {Function} callback for success
+                * @param err {Function} [optional] error callback
+                * @return {jqXHR}
                 */
                postWithEditToken: function( params, ok, err ) {
-                       var api = this;
+                       var api = this, useTokenToPost, getTokenIfBad;
                        if ( cachedToken === null ) {
                                // We don't have a valid cached token, so get a fresh one and try posting.
                                // We do not trap any 'badtoken' or 'notoken' errors, because we don't want
                                // an infinite loop. If this fresh token is bad, something else is very wrong.
-                               var useTokenToPost = function( token ) {
-                                       params.token = token; 
+                               useTokenToPost = function( token ) {
+                                       params.token = token;
                                        api.post( params, ok, err );
                                };
-                               api.getEditToken( useTokenToPost, err );
+                               return api.getEditToken( useTokenToPost, err );
                        } else {
                                // We do have a token, but it might be expired. So if it is 'bad' then
                                // start over with a new token.
                                params.token = cachedToken;
-                               var getTokenIfBad = function( code, result ) {
-                                       if ( code === 'badtoken' )  {
+                               getTokenIfBad = function( code, result ) {
+                                       if ( code === 'badtoken' ) {
                                                cachedToken = null; // force a new token
                                                api.postWithEditToken( params, ok, err );
                                        } else {
                                                err( code, result );
                                        }
                                };
-                               api.post( params, { 'ok' : ok, 'err' : getTokenIfBad });
+                               return api.post( params, { 'ok' : ok, 'err' : getTokenIfBad });
                        }
                },
-       
+
                /**
                 * Api helper to grab an edit token
-                *
+                *
                 * token callback has signature ( String token )
                 * error callback has signature ( String code, Object results, XmlHttpRequest xhr, Exception exception )
-                * Note that xhr and exception are only available for 'http_*' errors
+                * Note that xhr and exception are only available for 'http_*' errors
                 *  code may be any http_* error code (see mw.Api), or 'token_missing'
                 *
-                * @param {Function} received token callback
-                * @param {Function} error callback
+                * @param tokenCallback {Function} received token callback
+                * @param err {Function} error callback
+                * @return {jqXHR}
                 */
                getEditToken: function( tokenCallback, err ) {
-                       var api = this;
-
-                       var parameters = {                      
-                               'prop': 'info',
-                               'intoken': 'edit',
-                               /* we need some kind of dummy page to get a token from. This will return a response 
-                                  complaining that the page is missing, but we should also get an edit token */
-                               'titles': 'DummyPageForEditToken'
-                       };
-
-                       var ok = function( data ) {
-                               var token;
-                               $.each( data.query.pages, function( i, page ) {
-                                       if ( page['edittoken'] ) {
-                                               token = page['edittoken'];
-                                               return false;
+                       var parameters = {
+                                       prop: 'info',
+                                       intoken: 'edit',
+                                       // we need some kind of dummy page to get a token from. This will return a response
+                                       // complaining that the page is missing, but we should also get an edit token
+                                       titles: 'DummyPageForEditToken'
+                               },
+                               ok = function( data ) {
+                                       var token;
+                                       $.each( data.query.pages, function( i, page ) {
+                                               if ( page.edittoken ) {
+                                                       token = page.edittoken;
+                                                       return false;
+                                               }
+                                       } );
+                                       if ( token !== undefined ) {
+                                               cachedToken = token;
+                                               tokenCallback( token );
+                                       } else {
+                                               err( 'token-missing', data );
                                        }
-                               } );
-                               if ( token !== undefined ) {
-                                       cachedToken = token;
-                                       tokenCallback( token );
-                               } else {
-                                       err( 'token-missing', data );
-                               }
-                       };
-
-                       var ajaxOptions = {
-                               'ok': ok,
-                               'err': err,
-                               // Due to the API assuming we're logged out if we pass the callback-parameter,
-                               // we have to disable jQuery's callback system, and instead parse JSON string,
-                               // by setting 'jsonp' to false.
-                               'jsonp': false
-                       };
+                               },
+                               ajaxOptions = {
+                                       ok: ok,
+                                       err: err,
+                                       // Due to the API assuming we're logged out if we pass the callback-parameter,
+                                       // we have to disable jQuery's callback system, and instead parse JSON string,
+                                       // by setting 'jsonp' to false.
+                                       jsonp: false
+                               };
 
-                       api.get( parameters, ajaxOptions );
+                       return this.get( parameters, ajaxOptions );
                },
 
                /**
                 * Create a new section of the page.
-                * @param {mw.Title|String} target page
-                * @param {String} header
-                * @param {String} wikitext message
-                * @param {Function} success handler
-                * @param {Function} error handler
+                * @param title {mw.Title|String} target page
+                * @param header {String}
+                * @param message {String} wikitext message
+                * @param ok {Function} success handler
+                * @param err {Function} error handler
+                * @return {jqXHR}
                 */
                newSection: function( title, header, message, ok, err ) {
                        var params = {
                                summary: header,
                                text: message
                        };
-                       this.postWithEditToken( params, ok, err );
+                       return this.postWithEditToken( params, ok, err );
                }
 
-        } ); // end extend
+        } );
 
-} )( window.mediaWiki, jQuery );
+} )( jQuery, mediaWiki );
index eafee05..ac8bfd4 100644 (file)
-/* mw.Api objects represent the API of a particular MediaWiki server. */       
+/* mw.Api objects represent the API of a particular MediaWiki server. */
+
+( function( $, mw, undefined ) {
 
-( function( mw, $j, undefined ) {
-       
        /**
-        * Represents the API of a particular MediaWiki server.
-        *
-        * Required options: 
-        *   url - complete URL to API endpoint. Usually equivalent to wgServer + wgScriptPath + '/api.php'
-        *
-        * Other options:
-        *   can override the parameter defaults and ajax default options.
-        *      XXX document!
-        *  
-        * TODO share api objects with exact same config.
-        *
-        * ajax options can also be overriden on every get() or post()
-        * 
-        * @param options {Mixed} can take many options, but must include at minimum the API url.
+        * @var defaultsOptions {Object}
+        * We allow people to omit these default parameters from API requests
+        * there is very customizable error handling here, on a per-call basis
+        * wondering, would it be simpler to make it easy to clone the api object,
+        * change error handling, and use that instead?
         */
-       mw.Api = function( options ) {
+       var defaultsOptions = {
 
-               if ( options === undefined ) {
-                       options = {};
-               }
-
-               // make sure we at least have a URL endpoint for the API
-               if ( options.url === undefined ) {
-                       options.url = mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + '/api' + mw.config.get( 'wgScriptExtension' );
-               }
-
-               this.url = options.url;
-
-               /* We allow people to omit these default parameters from API requests */
-               // there is very customizable error handling here, on a per-call basis
-               // wondering, would it be simpler to make it easy to clone the api object, change error handling, and use that instead?
-               this.defaults = {
+                       // Query parameters for API requests
                        parameters: {
                                action: 'query',
                                format: 'json'
                        },
 
+                       // Ajax options for jQuery.ajax()
                        ajax: {
-                               // force toString if we got a mw.Uri object
-                               url: new String( this.url ),  
+                               url: mw.util.wikiScript( 'api' ),
 
-                               /* default function for success and no API error */
                                ok: function() {},
 
                                // caller can supply handlers for http transport error or api errors
                                err: function( code, result ) {
-                                       mw.log( "mw.Api error: " + code, 'debug' );
+                                       mw.log( 'mw.Api error: ' + code, 'debug' );
                                },
 
-                               timeout: 30000, /* 30 seconds */
+                               timeout: 30000, // 30 seconds
 
                                dataType: 'json'
-
                        }
                };
 
+       /**
+        * Constructor to create an object to interact with the API of a particular MediaWiki server.
+        *
+        * @todo Share API objects with exact same config.
+        * @example
+        * <code>
+        * var api = new mw.Api();
+        * api.get( {
+        *     action: 'query',
+        *     meta: 'userinfo'
+        * }, {
+        *     ok: function () { console.log( arguments ); }
+        * } );
+        * </code>
+        *
+        * @constructor
+        * @param options {Object} See defaultOptions documentation above. Ajax options can also be
+        * overridden for each individual request to jQuery.ajax() later on.
+        */
+       mw.Api = function( options ) {
 
-               if ( options.parameters ) {
-                       $j.extend( this.defaults.parameters, options.parameters );
+               if ( options === undefined ) {
+                       options = {};
                }
 
-               if ( options.ajax ) { 
-                       $j.extend( this.defaults.ajax, options.ajax );
+               // Force toString if we got a mw.Uri object
+               if ( options.ajax && options.ajax.url !== undefined ) {
+                       options.ajax.url = String( options.ajax.url );
                }
+
+               options.parameters = $.extend( {}, defaultsOptions.parameters, options.parameters );
+               options.ajax = $.extend( {}, defaultsOptions.ajax, options.ajax );
+
+               this.defaults = options;
        };
 
        mw.Api.prototype = {
 
                /**
                 * For api queries, in simple cases the caller just passes a success callback.
-                * In complex cases they pass an object with a success property as callback and probably other options.
+                * In complex cases they pass an object with a success property as callback and
+                * probably other options.
                 * Normalize the argument so that it's always the latter case.
-                * 
-                * @param {Object|Function} ajax properties, or just a success function
-                * @return Function
+                *
+                * @param {Object|Function} An object contaning one or more of options.ajax,
+                * or just a success function (options.ajax.ok).
+                * @return {Object} Normalized ajax options.
                 */
                normalizeAjaxOptions: function( arg ) {
+                       var opt = arg;
                        if ( typeof arg === 'function' ) {
-                               var ok = arg;
-                               arg = { 'ok': ok };
+                               opt = { 'ok': arg };
                        }
-                       if (! arg.ok ) {
-                               throw Error( "ajax options must include ok callback" );
+                       if ( !opt.ok ) {
+                               throw new Error( 'ajax options must include ok callback' );
                        }
-                       return arg;
+                       return opt;
                },
 
                /**
                 * Perform API get request
                 *
-                * @param {Object} request parameters 
-                * @param {Object|Function} ajax properties, or just a success function
-                */     
+                * @param {Object} request parameters
+                * @param {Object|Function} ajax options, or just a success function
+                * @return {jqXHR}
+                */
                get: function( parameters, ajaxOptions ) {
                        ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
                        ajaxOptions.type = 'GET';
-                       this.ajax( parameters, ajaxOptions );
+                       return this.ajax( parameters, ajaxOptions );
                },
 
                /**
                 * Perform API post request
-                * TODO post actions for nonlocal will need proxy 
-                * 
-                * @param {Object} request parameters 
-                * @param {Object|Function} ajax properties, or just a success function
+                * @todo Post actions for nonlocal will need proxy
+                *
+                * @param {Object} request parameters
+                * @param {Object|Function} ajax options, or just a success function
+                * @return {jqXHR}
                 */
                post: function( parameters, ajaxOptions ) {
                        ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
                        ajaxOptions.type = 'POST';
-                       this.ajax( parameters, ajaxOptions );
+                       return this.ajax( parameters, ajaxOptions );
                },
 
                /**
-                * Perform the API call. 
-                * 
-                * @param {Object} request parameters 
-                * @param {Object} ajax properties
+                * Perform the API call.
+                *
+                * @param {Object} request parameters
+                * @param {Object} ajax options
+                * @return {jqXHR}
                 */
                ajax: function( parameters, ajaxOptions ) {
-                       parameters = $j.extend( {}, this.defaults.parameters, parameters );
-                       ajaxOptions = $j.extend( {}, this.defaults.ajax, ajaxOptions );
+                       parameters = $.extend( {}, this.defaults.parameters, parameters );
+                       ajaxOptions = $.extend( {}, this.defaults.ajax, ajaxOptions );
 
                        // Some deployed MediaWiki >= 1.17 forbid periods in URLs, due to an IE XSS bug
                        // So let's escape them here. See bug #28235
                        // This works because jQuery accepts data as a query string or as an Object
-                       ajaxOptions.data = $j.param( parameters ).replace( /\./g, '%2E' );
-               
+                       ajaxOptions.data = $.param( parameters ).replace( /\./g, '%2E' );
+
                        ajaxOptions.error = function( xhr, textStatus, exception ) {
-                               ajaxOptions.err( 'http', { xhr: xhr, textStatus: textStatus, exception: exception } );
+                               ajaxOptions.err( 'http', {
+                                       xhr: xhr,
+                                       textStatus: textStatus,
+                                       exception: exception
+                               } );
                        };
 
-                       
-                       /* success just means 200 OK; also check for output and API errors */
+                       // Success just means 200 OK; also check for output and API errors
                        ajaxOptions.success = function( result ) {
                                if ( result === undefined || result === null || result === '' ) {
-                                       ajaxOptions.err( "ok-but-empty", "OK response but empty result (check HTTP headers?)" );
+                                       ajaxOptions.err( 'ok-but-empty',
+                                               'OK response but empty result (check HTTP headers?)' );
                                } else if ( result.error ) {
                                        var code = result.error.code === undefined ? 'unknown' : result.error.code;
                                        ajaxOptions.err( code, result );
-                               } else { 
+                               } else {
                                        ajaxOptions.ok( result );
                                }
                        };
 
-                       $j.ajax( ajaxOptions );
-
+                       return $.ajax( ajaxOptions );
                }
 
        };
 
        /**
-        * This is a list of errors we might receive from the API.
+        * @var {Array} List of errors we might receive from the API.
         * For now, this just documents our expectation that there should be similar messages
         * available.
         */
        mw.Api.errors = [
-               /* occurs when POST aborted - jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result */
+               // occurs when POST aborted
+               // jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result
                'ok-but-empty',
 
                // timeout
                'timeout',
 
-               /* really a warning, but we treat it like an error */
+               // really a warning, but we treat it like an error
                'duplicate',
                'duplicate-archive',
 
-               /* upload succeeded, but no image info. 
-                  this is probably impossible, but might as well check for it */
+               // upload succeeded, but no image info.
+               // this is probably impossible, but might as well check for it
                'noimageinfo',
 
-               /* remote errors, defined in API */
+               // remote errors, defined in API
                'uploaddisabled',
                'nomodule',
                'mustbeposted',
        ];
 
        /**
-        * This is a list of warnings we might receive from the API.
+        * @var {Array} List of warnings we might receive from the API.
         * For now, this just documents our expectation that there should be similar messages
         * available.
         */
-
        mw.Api.warnings = [
                'duplicate',
                'exists'
        ];
 
-}) ( window.mediaWiki, jQuery );
+})( jQuery, mediaWiki );
index 7bcc4bb..429b9d1 100644 (file)
@@ -1,29 +1,31 @@
-// library to assist with action=parse, that is, get rendered HTML of wikitext
+/**
+ * Additional mw.Api methods to assist with API calls related to parsing wikitext.
+ */
 
-( function( mw, $ ) {
+( function( $, mw ) {
 
-       $.extend( mw.Api.prototype, { 
+       $.extend( mw.Api.prototype, {
                /**
-                * Parse wikitext into HTML
-                * @param {String} wikitext
-                * @param {Function} callback to which to pass success HTML
-                * @param {Function} callback if error (optional)
+                * Convinience method for 'action=parse'. Parses wikitext into HTML.
+                *
+                * @param wikiText {String}
+                * @param success {Function} callback to which to pass success HTML
+                * @param error {Function} callback if error (optional)
+                * @return {jqXHR}
                 */
-               parse: function( wikiText, useHtml, error ) {
+               parse: function( wikiText, success, error ) {
                        var params = {
-                               text: wikiText,
-                               action: 'parse'
-                       };
-                       var ok = function( data ) {
-                               if ( data && data.parse && data.parse.text && data.parse.text['*'] ) {
-                                       useHtml( data.parse.text['*'] );
-                               } 
-                       };
-                       this.get( params, ok, error );
+                                       text: wikiText,
+                                       action: 'parse'
+                               },
+                               ok = function( data ) {
+                                       if ( data && data.parse && data.parse.text && data.parse.text['*'] ) {
+                                               success( data.parse.text['*'] );
+                                       }
+                               };
+                       return this.get( params, ok, error );
                }
 
+       } );
 
-       } ); // end extend
-} )( window.mediaWiki, jQuery );
-
-
+} )( jQuery, mediaWiki );
index 95bbc4f..1e2ed35 100644 (file)
@@ -1,48 +1,51 @@
-// library to assist with API calls on titleblacklist
+/**
+ * Additional mw.Api methods to assist with API calls to the API module of the TitleBlacklist extension.
+ */
 
-( function( mw, $ ) {
+( function( $, mw, undefined ) {
 
-       // cached token so we don't have to keep fetching new ones for every single post
-       var cachedToken = null;
-
-       $.extend( mw.Api.prototype, { 
+       $.extend( mw.Api.prototype, {
                /**
-                * @param {mw.Title} 
-                * @param {Function} callback to pass false on Title not blacklisted, or error text when blacklisted
-                * @param {Function} optional callback to run if api error
-                * @return ajax call object
+                * Convinience method for 'action=titleblacklist'.
+                * Note: This action is not provided by MediaWiki core, but as part of the TitleBlacklist extension.
+                *
+                * @param title {mw.Title}
+                * @param success {Function} Called on successfull request. First argument is false if title wasn't blacklisted,
+                *  object with 'reason', 'line' and 'message' properties if title was blacklisted.
+                * @param err {Function} optional callback to run if api error
+                * @return {jqXHR}
                 */
-               isBlacklisted: function( title, callback, err ) {
-                       var params = {
-                               'action': 'titleblacklist',
-                               'tbaction': 'create',
-                               'tbtitle': title.toString()
-                       };
-
-                       var ok = function( data ) {
-                               // this fails open (if nothing valid is returned by the api, allows the title)
-                               // also fails open when the API is not present, which will be most of the time.
-                               if ( data.titleblacklist && data.titleblacklist.result && data.titleblacklist.result == 'blacklisted') {
+               isBlacklisted: function( title, success, err ) {
+                       var     params = {
+                                       action: 'titleblacklist',
+                                       tbaction: 'create',
+                                       tbtitle: title.toString()
+                               },
+                               ok = function( data ) {
                                        var result;
-                                       if ( data.titleblacklist.reason ) {
-                                               result = {
-                                                       reason: data.titleblacklist.reason,
-                                                       line: data.titleblacklist.line,
-                                                       message: data.titleblacklist.message
-                                               };
+
+                                       // this fails open (if nothing valid is returned by the api, allows the title)
+                                       // also fails open when the API is not present, which will be most of the time
+                                       // as this API module is part of the TitleBlacklist extension.
+                                       if ( data.titleblacklist && data.titleblacklist.result && data.titleblacklist.result === 'blacklisted') {
+                                               if ( data.titleblacklist.reason ) {
+                                                       result = {
+                                                               reason: data.titleblacklist.reason,
+                                                               line: data.titleblacklist.line,
+                                                               message: data.titleblacklist.message
+                                                       };
+                                               } else {
+                                                       mw.log('mw.Api.titleblacklist::isBlacklisted> no reason data for blacklisted title', 'debug');
+                                                       result = { reason: 'Blacklisted, but no reason supplied', line: 'Unknown', message: null };
+                                               }
+                                               success( result );
                                        } else {
-                                               mw.log("mw.Api.titleblacklist::isBlacklisted> no reason data for blacklisted title", 'debug');
-                                               result = { reason: "Blacklisted, but no reason supplied", line: "Unknown" };
+                                               success ( false );
                                        }
-                                       callback( result );
-                               } else {
-                                       callback ( false );
-                               }
-                       };
+                               };
 
                        return this.get( params, ok, err );
-
                }
 
        } );
-} )( window.mediaWiki, jQuery );
+} )( jQuery, mediaWiki );