UCP JavaScript changes

This is a list of changes that wikis may need to make when making their custom JavaScript UCP-compatible during Phase 1. See also the list of different/renamed classes for changes that may need to be made to CSS selectors within custom JavaScript.
== Mastheads ==
User profile mastheads are now lazy-loading. While we do not know for sure whether this behavior will remain until the end of Phase 1, something similar to the following can be used to wait for the masthead to load before attempting any actions with it:
var interval = setInterval(function() {
 if ($('#userProfileApp').length) {
 clearInterval(interval);
 // You can now do stuff with the masthead.
 }
 // Change 1000 to the amount of seconds you want to be rechecking
 // whether the masthead exists.
}, 1000);
To detect whether a masthead is supposed to load on a page, you can search for one of the profile-prefixed globals, such as mw.config.get('profileUserName').
== AMD ==
Legacy MediaWiki used [ AMD]'s require and define functions to separate Fandom-specific JavaScript into modules. UCP does not, and so places where these functions were used will throw errors.
AMD has been replaced with MediaWiki's mw.loader methods, such as mw.loader.using and mw.loader.require, and AMD modules have been replaced with regular ResourceLoader modules. mw.loader.require can be passed a ResourceLoader module name to retrieve the object associated with that module. mw.loader.using can be used to load ResourceLoader modules required for your script to function:
mw.loader.using('mediawiki.api').then(function() {
 // You can now use mw.Api.
});
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function() {
 // You can use mw.Api and mw.util.
});
$.when($someDeferredInstance, mw.loader.using('mediawiki.api')).then(function() {
 // mw.loader.using returns a $.Deferred instance that can be
 // awaited with other $.Deferred in constructs such as $.when.
});
A lot of useful ResourceLoader modules now have randomized suffixes, such as isTouchScreen-0264e82b.js. To find exact names of these modules, you can use the following:
var moduleNames = mw.loader.getModuleNames().filter(function(moduleName) {
 return moduleName.indexOf('isTouchScreen-') === 0;
});
if (moduleNames.length) {
 var isTouchScreen = mw.loader.require(moduleNames[0]).isTouchScreen;
 console.info('Is your screen touchable?', isTouchScreen());
}
=== AMD module replacements ===
* wikia.window, mw and jquery modules need no replacement. If you were requiring only these modules in a require() call, you do not need that require call and can just replace it with an IIFE.
* wikia.browserDetect does not have a replacement, but isTouchScreen-SUFFIX can be used to detect whether the device is a mobile device instead.
* If your code was using banner notifications, you may want to consider using mw.notify instead.
** If you were previously inserting HTML into your notifications, you will have to wrap it in a jQuery or a DOM node before passing it to mw.notify. If you were previously escaping it, you no longer need to do that.
* wikia.nirvana and $.nirvana are no longer available, but you can use the nirvana-SUFFIX module instead. However, as it only includes a sendRequest function (and no longer getJson/postJson functions), you may want to consider just sending a plain HTTP request to Nirvana (via $.get, $.post, $.ajax or fetch).
== OOUI ==
A bunch of forms, as well as all modals ($.showCustomModal, wikia.ui.modal), on the UCP now use OOUI. The use of jQuery UI as well as some other core modules is now deprecated in favor of OOUI. Migration guides for legacy components to OOUI are coming.
Porting scripts that make use of $.showCustomModal can be done conveniently by importing the ShowCustomModal library.
== jQuery ==
Here are listed differences under the $ global object, that may be related to jQuery or Fandom-specific modules adding their interface through them.
* The module jquery.autocomplete has been renamed to jquery.ui.autocomplete.
* The function $(...).exists() ($.fn.exists) no longer exists. You can use $(...).length ($.fn.length) instead.
* $.storage no longer exists. You can use mw.storage (which is a wrapper around localStorage that doesn't throw any errors) with similar get and set methods, but these can only store plain strings that will have to be parsed with JSON.parse when read and stringifed with JSON.stringify when written (setObject and getObject are available on newer MediaWiki versions).
* $.getUrlVar does not exist. You need to ensure the mediawiki.util module has loaded and then use mw.util.getParamValue.
* There were a couple of changes to how $.Deferred() instances work in newer versions of jQuery:
** They are behaving more in-line with how Promise instances work. This means .then(...) callbacks are executed asynchronously even if their promises have already resolved.
** .error(...) no longer exists on the UCP, and .fail(...) should be used instead.
* $.escapeRE no longer exists. You can use mw.RegExp.escape instead (please note this has changed to mw.util.escapeRegExp in MediaWiki 1.34, so add a fallback to that too).
== Wiki theme colors ==
As the wgSassParams global is no longer available (presumably due to Fandom no longer using SCSS), wiki theme colors will have to be grabbed directly from the page. An exception to this is ThemeDesigner, where mw.config.get('themeSettings') can be used.
You can see examples of how theme colors can be fetched in the source code for the Colors library - color-body, color-body-middle (should always be the same as color-body) and color-community-header can be fetched from background colors of respective elements and color-links, color-page and color-buttons can be fetched from respective CSS variables set on the :root element.
== Editor ==
The new editor is more-or-less completely different from all three editors used on legacy Fandom. Here are only listed some of differences that most often cause errors in scripts.
* The wgAction global does not change to edit while under the new VisualEditor. You can use the wgIsProbablyEditable global and a hook to wait for the editor to load. Note that you may still want to check for wgAction on pages where the new VisualEditor has been disabled (currently possible via ?action=edit&venoscript=1&debug=1 or ?action=submit URL parameters, or when undoing an edit, or when the user chooses the 2010 Source Editor as their preferred editor on their Preferences).
* To check whether the regular source editor or the code editor is being used, you may want to check the wgPageContentModel global.
== importArticles ==
* Article syntax for importArticles no longer assumes JavaScript pages cannot be located under the main namespace and tries to load them from there instead of redirecting to the MediaWiki namespace. As a result, 'u:dev:DiscordIntegrator/code.js' is no longer equal to 'u:dev:MediaWiki:DiscordIntegrator/code.js'.
* You currently can't pass multiple objects in importArticles's parameters. If you did, you now need to split it into multiple function calls.
* Passing multiple articles of the same name in the same call throws an error.
== Globals ==
* addOnloadHook function does not exist. Replacing it with just $ should work.
* Fetching some global variables directly from global scope instead of via mw.config (for example, wgUserName or window.wgUserName instead of mw.config.get('wgUserName') is now going to throw warnings in your browser console (but still work).
* Underscore.js is not available on the UCP. If you were using the _ global object for anything, you might be able to substitute it with the lodash-SUFFIX ResourceLoader module which has some functionality of Underscore.js. Check out lodash's official guide for migrating from Underscore.js.
* The window.Wikia object does not exist.
* wgIsMainPage does not exist. You can use the wgMainPageTitle global, but make sure that the page name you're comparing it with (for example, wgPageName) does not contain underscores instead of spaces.
** A way to approach this would be mw.config.get('wgPageName').replace(/_/g, ' ') === mw.config.get('wgMainPageTitle').
* wgCityId is now a number instead of a string.
* wgTrackID doesn't exist. wgUserId, however, exists on both legacy and UCP.
* wgCatId doesn't exist, but its string variant, wikiVertical exists. On legacy, it's called wgWikiVertical.
== MediaWiki API ==
* Obtaining tokens now must be done through action=query&meta=tokens, as other methods of obtaining tokens have been deprecated.
== Other differences ==
* mediawiki.util is no longer loaded before custom JavaScript executes. If your code used mw.util and didn't wait for the module to load, it will need to use mw.loader.using('mediawiki.util').then(function() {/* your code */}) to wait for the mw.util methods to become available.
* The string <script> (outside of code comments, as these are stripped by ResourceLoader) in your personal or site-wide JavaScript may break all JavaScript loaded by Fandom.
* If your code was using query-continue on legacy, you may need to switch to using rawcontinue on the UCP.
* The debug mode does not currently work, so you will have to wait for ResourceLoader cache to refresh while debugging your through JavaScript pages.
* The loaded on #WikiaRail is now is-ready, in case your code was checking the former to see whether the Rail has already loaded.
* Wikitext parser output (on-page, as well as action=parse) is now wrapped in a .mw-parser-output element.
* The Facebook spinner icon does not exist on UCP, but you may want to use the mw-ajax-loader for a loader icon instead.
* Defining variables outside of functions no longer makes them global (placed under window) as ResourceLoader wraps all custom JS in a function (so they are function-scoped, not global-scoped).
* When an error occurs during an API call, mw.Api rejects the promise instead of resolving it. That means if your API error handling was in the .done(...) call, it must be moved to the .fail(...) call. The first parameter of the function passed to .fail(...) is the error code (set to http if it was an AJAX call error, which was previously the only reason why this callback would be called) and the second is the actual error object.
* mediawiki.action.history.diff ResourceLoader module is now mediawiki.diff.styles.
* The ext.wikia.LinkSuggest module is not available due to its functionality not being ported to UCP yet (but is planned to be added).
== See also ==
* Upstream MediaWiki JavaScript documentation
* ResourceLoader migration guide for users on MediaWiki.org
Category:Guides