Gadget kitchen/January 2012 training

Gadget tutorial: notes for Brion Vibber's tutorial at the San Francisco Hackathon January 2012 Please feel free to improve formatting or add links, but please do not significantly change the structure of this document or add or remove sections. It's meant for the students to see so they can follow along with the video.

Customizing Wikipedia with Javascript, User Scripts and Gadgets, San Francisco Hackathon January 2012

One of our core values: You can customize the software to do what you want. MediaWiki is FLOSS but runs on a server, so you can't change it directly. But really MediaWiki is two programs:

  • serverside in PHP
  • clientside in HTML/JS

And you can easily modify the latter. A user script is similar to a Greasemonkey extension for Firefox. It is an extension that lets you write clientside JavaScript which will be loaded after the website finishes loading, thus allowing your script to alter the page. It's personal: it only runs for users that install or enable it. But you don't need browser additions to add JavaScript customizations, because we have provided a place in MediaWiki itself for you to plug things in. Check out this intro page on User Scripts and Gadgets: Gadget kitchen

An alternate take of the talk -- Customizing Wikipedia with Javascript, User Scripts and Gadgets, San Francisco Hackathon January 2012



There are 3 ways to insert additional JavaScript into the system.

  1. A user script just belongs to you as a user
    • We let you do anything you want.
    • Anything you can do in JS
    • No security concerns. Only runs as you.
    • No one else automatically gets that script, except by copying your userscript page.
    • "you can XSS yourself"
  2. A gadget is shared among all users of a wiki, runs for whomever enables it in their user preferences.
    • Gadgets are created and managed by wiki-admins
    • Wikipedia has a vetting process for which gadgets are available.
  3. The siteJS is located at MediaWiki:Common.js
    • Affects everyone. Runs automatically for both logged-out and logged-in users.
    • Only the administrators of that wiki can change its Common.js
    • Extra sidebar-tools are often added through siteJS

A gadget is shared among multiple users. For example, if you log in to and go to your user preferences, and click the Gadgets tab, look at those options with checkboxes. Sometimes people will write a user script to prototype it for a gadget or the Site JS. Explain here that all these things are just executing JavaScript on the client side. They're all ways of doing the same thing.

Question: Can I write a gadget and make that run, on my wiki, for anon logged-in users?
Yes, but it is not as simple as it should be. You have to include the code for that gadget in the global site JS. But Gadgets is being rewritten. Ask Roan outside this room about the future of gadgets, which will make certain things easier.

How to Write A User Script

  • Log in to; create a user account if you haven't already.
  • Go to your preferences and click the Gadgets tab.
  • Let's turn on Code Editor, which Brion wrote.
  • Now, go to Appearance tab under "My preferences"
    • Shared CSS/JS for all skins, click the link for "Custom JavaScript".
  • Now you are editing User: (you)/common.js which is just a wiki page like any other. We turned on CodeEditor gadget, so we have line numbers, syntax highlighting etc.
alert("Hello world");

or try to change title or background color.

    • Just hit "Save page" and then that thing will happen.

Messing with jQuery

  • We also have jQuery!
$('#content').css('border', '10px solid red');
  • In Gadget Kitchen, do these steps:
  • Gadget kitchen#I want to try!
  • Notice that we still have the border on the page. Refresh and the border is gone.
  • Sample code adds a link to the toolbox section on sidebar. Click it and it pops up dialog box with list of recently changed pages. This shows and does several things: adds to UI, makes interactive, uses MediaWiki REST API.
  • Take a look at mw.loader.using and similar functions. These functions are what MW itself uses and you can use them too. Anything in mw.* namespace should be reliable for future versions. Now, tells our JS module system, have you loaded jquery.ui.dialog plugin to make dialogs? If not, please load it.
  • To find out what modules are available by default on a plain MediaWiki install, check out ResourceLoader/Default modules. (or look at the SVN snapshot of Resources.php, the module registry).

How our JavaScript/jQuery calls work


"Hope you like closures! You're gonna use them a lot!" There's a list of modules to load, and a function to run when it's loaded. You don't have to worry about module load order. We have straightforward code in here - jQuery, jqueryui dialog plugin, tell it string & size, contents, it makes a dialog. jQuery.getJSON loads things from our action API. There are standard jQuery functions for doing HTTP fetch of JSON data. We Use a little mw.util function called wikiScript to get the URL to the API. (There are easier ways to do this in 1.19 coming up that encapsulate API access stuff. MW 1.19 will be out in March probably.) Sample code: there are some parameters, function returns your data, goes through that, build some stuff.

Using our action API


Now, look at action API help.

This gives you all the modules, parameters, sample links.

  • Also check out the query sandbox: Special:ApiSandbox. Tells you what an API call would look like. (Coded by Max Semenik) Good for:
    • "I wanna do some query that pulls this data, not sure how to do it."


  • Idea: query, fetch all pages.
  • Hit Make Request button. This is the JSON we get back.

Back to the tutorial JS


At the end here is our ready function. jQuery's .ready waits to do stuff until the page is fully initialized. THEN go through and add links. utility function: mw.util.addPortletLink which is kind of cryptic (unfortunately does not tell you which portals exist), but documented over on ResourceLoader/Default modules.

TODO: improve Default modules docs.

Standard jQuery code at the end of the new common.js ... add an event that calls our code.

Ideas for exercises

  • More elaborate: try to localise this!
    • (idea: localise? because what about cross-loading JS? too advanced for this)
  • Change the query re the sidebar popup.

Make it a tab!


How do I make a tab? Look at your user JS in User:(you):Common.js. Look in the default modules. addPortletLink.

    • On line 75 of common.js.

addPortletLink call - changed destination parameter -- Change from the toolbar p-tb to a tab p-cactions and hit Save. "Quick changelog" now shows up in dropdown near the searchbox.

  • Reminder: use Firebug! or dev tools in chrome or safari.

Now let's try replacing that with p-views and hit Save -- and now it is a tab near the Edit etc.

Exercise idea


Can we add another action API call? Page history of the page you're on.

  • Back to API sandbox.
  • format=json is what you always want.
  • action=query
  • prop=revisions
  • rvprop = comment
  • titles=Main Page ## example

So let's go back to our code in common.js and change the query we make -- line 47, 'prop': 'revisions'; and rvprop is comment

  • 'titles': mw.config.get('wgPageName'); ### should be documented somewhere in here.
  • separate plurals by vertical bar
  • If you have a JS console like firebug, run the little snippets!
  • instead of query=recentchanges, we now have query=changes (change line 54 as well)
    • array is indexed by pageid,so you need to find the pageid to get the other ones.
TODO: Brion to pretest this particular change.

Next exercise:

Show how to turn this into a gadget


Look at a Special:Gadgets page such as . This is a list of gadgets. Look at definitions. Anyone can see this page. You have to be an admin to edit it. On our wikis, you have to be an admin to edit this.

  • There is a defn file that is a little list. You can define mult sections. Each line is a single item.
    • example: CodeEditor. Name, compat with RL, needs to load this module, and then actual page file.
  • Go to Gadget-Codeeditor.js -- you see where it loads it from where its actual code lives.

To turn your US into a gadget:

  • you find admins, say you want to set something up as a gadget. They can copy your gadget into a gadget definition.

Q: What's the protocol for turning my US into an en.wp gadget? Answer: Look at

  • "Proposal" is active, "Evaluation" is not.
  • Tell Sumana so she can help you move forward in the process.

A note to future presenters: ensure that students do more typing, less copy-pasting! Take the basic bits in part by part.'