Thread:Pecoes/@comment-4674838-20121105085352/@comment-3508190-20121106091559

The first thing you need to know about Preferences is that getting and setting preferences is a completely different scenario from offering them to the user for manipulation on Special:Scripts. You will have to write code for both scenarios and use the same API, but in ways that are so different that it's best to split the code in two parts.

I've coined my own terminology for the two kinds of code: The code that reads the preferences is the "main script" and the code for Special:Scripts is the "form script".

The main script is the more important of the two. It needs to be loaded on every page - including Special:Scripts. That's because the main script needs to provide the URL of the form script. Preferences will load that form script when necessary.

Before we can look at a first example we have to get a major idiosyncrasy of Preferences out of the way. For performance reasons it would be best not to load the Preferences module but to include its code directly into your own. The Preferences module is however a bit large and would add a lot of bloat to your code. That's doubly and triply true if the user installs more than one addon that uses the Preferences module. I've tried to escape that trap by splitting the module into several chunks and creating a tiny small rump module that I call the loader. The loader adds a single method to the Preferences module that you can use right away and also loads the other chunks of the module.

The loader is less than 1K in size so you can copypaste it into your code without worrying about bloat. Alternatively you could also substitute it as

That one method of the loader is also the one and only method of the Preferences module. You will use this method to queue callbacks functions that will be executed once the other chunks of the module and the actual user preferences have fully loaded.

The method is called "addon" and it returns an object that I call a "Promise". A "Promise" is a promise because the module promises to call your callback function when its time comes:

Note that the moment you request the promise is also the moment you identify your addon to the Preferences module.

The Promise actually promises more than one thing. It promises different things to main scripts than to form scripts. The most important promises are therefore called "main" and "form":

The callback to the main promise will be executed on all pages except Special:Scripts. And the script you provide to form will be loaded and executed on Special:Scripts only.

Let's forget about the form promise (and the other promises) for the moment and focus on the main promise because that's where the main action is at. Figuratively speaking.

The callback to the main promise receives another kind of object as its parameter. This object will allow you to get and set the user's preferences:

local and global return mediaWiki.Map objects which are essentially plain objects with a little bit of sugar like a get, a set, an exists and a log method.

The data object is simply called a "Main" object btw. Besides the local and the global method it also has a shared method. Before we can take a look at that, we need to get one final idiosyncrasy out of the way: The handling of shared objects.

The user's local and global data is loaded by default and on every page - even if you don't plan to use it. That happens with the same request that also loads the other chunks of the module. That means it's handled very efficiently. The shared preferences however are stored separately and requesting them is a bit less efficient. That's why they're not loaded by default and you have to request them explicitly. But that shouldn't be a problem because you probably don't want the current users shared data anyway. You will want the shared data of the user whose page the current user is visiting. Or you will want the shared data of the current user's friends. etc.

As you can see from the example you have to specify to Promise.main whose users' shared data you want to load. You will also have to specify the user explicitly when you access the data with Main.shared.

That's the 80/20 you need to know about main scripts. Next up: Form scripts.