InfoWidgets/Advanced guide

__NOTOC__
The methods you call for the preconfigured widgets contain no active code - just data. Let's take Widget.stubs as an example:
stubs: function () {
 return {
 type: 'api',
 params: {
 action: 'query',
 format: 'json',
 list: 'categorymembers',
 cmtitle: 'Category:Article stubs',
 cmlimit: 10,
 cmsort: 'timestamp'
 }};
},
You may override all of these properties. There are other optional properties you can add. And you've already seen there's one property you must set yourself: the selector (see the Quickstart guide).
== Widget properties ==
Name 	Type 	Optional	Default
active 	Boolean 	Yes 	true
format 	Callback	Yes 	See text
maxResults	Integer 	Yes 	10
preload 	Callback	Yes 	See text
postload 	Callback	Yes 	See text
fallback 	String 	Yes 	None
type 	String 	No 	None
params 	Object 	No 	None
traversal 	Array 	See text	See text
error 	Callback	Yes 	Empty function
== widget.active ==
You can use this prop to deactivate and subsequently reactivate widgets. Just set it to false if you want to prevent a widget from updating and back to true when you want it to update again. All by itself this will not reset the update-interval. So if you don't want to wait up to 60 seconds to see your reactivated widget load, you also need to call Widgets.restart() afterwards.
== widget.format ==
This function is called when the widget is updated. It receives a plain array with the page titles as the first and the value of maxResults as the second parameter. This function is expected to return the HTML that is written into the container.
The most simple version would look like this:
function format (titles, maxResults) {
 var html = ;
 for (var i = 0; i < Math.min(titles.length, maxResults); i++) {
 html += '<a href="/wiki/'+titles[i]+'">'+titles[i]+'</a>';
 }
 return html.length ? ''+html+'' : ;
}
Note however that titles may show up more than once. If a page has been edited twice in a short period of time e.g. it will also show up twice in the recentchanges listing. That's why the default function filters out doublettes:
function format (titles, maxResults) {
 var html = ;
 var doublettes = [];
 for (var i = 0; i < titles.length && doublettes.length <= maxResults; i++) {
 if (-1 == $.inArray(titles[i], doublettes)) {
 doublettes.push(titles[i]);
 html += '<a href="/wiki/'+titles[i]+'">'+titles[i]+'</a>';
 }
 }
 return html.length ? ''+html+'' : ;
}
== widget.maxResults ==
Use this to specify how many links at most you want the widget to display. This prop is only used in widget.format. So feel free to ignore it, if you intend to write widget.format yourself.
== widget.preload ==
This function is called after the container is emptied and before the AJAX request is made. You can use it to give the visitor some feedback that new contents are loading. This is the default function:
preload: function (container) {
 container.css({
 backgroundImage: 'url(https://images.wikia.nocookie.net/dev/images/8/82/Facebook_throbber.gif)',
 backgroundRepeat: 'no-repeat',
 backgroundPosition: 'center'
 });
}
And this is the default image:
== widget.postload ==
This function is the counterpart to widget.preload. It is called after the AJAX request has finished - even if it failed - and after the container is filled with the results of widget.format(). This is the default function:
postload: function (container) {
 container.css( {backgroundImage: 'none'} );
}
== widget.type ==
This value tells the InfoWidgets whether to make an API request (value: "api") or and atom request (value: "rss"). This property must be set.
== widget.params ==
This is where the real action takes place. This (sub)object contains all the query-parameters that are sent to Fandom to perform an [/api.php API] or an atom request. While this is the most interesting part, it is unfortuntely also the one that's way beyond the scope of this guide. Fortunately however the [/api.php API] is quite self-documenting.
Transcoding an API request to a widget configuration is pretty straight-forward. Let's take an example:
[/api.php?action=query&list=backlinks&bltitle=Fandom+Developers+Wiki&bllimit=10 /api.php?action=query&list=backlinks&bltitle=Fandom+Developers+Wiki&bllimit=10]
This query lists all the pages on this wiki that link to the main page (""). The widget configuration would look like this:
var backLinks = {
 type: 'api',
 params: {
 action: 'query',
 list: 'backlinks',
 bllimit: 10
}};
There's one parameter missing however: bltitle (the page title). Manually entering a page name here would be silly of course. We want the current page's name. Fortunately every page on this and every other wiki includes a large set of global variables that provide lots of information about (among other things) the current page. We will use the variable wgTitle which contains the current page's title:
var backLinks = {
 type: 'api',
 params: {
 action: 'query',
 list: 'backlinks',
 bltitle: window.wgTitle !== undefined && wgTitle ? wgTitle : ,
 bllimit: 10
}};
== widget.traversal ==
All of the pre-configured widgets produce very similar replies from the [/api.php API]. This is the server's reply to the newPages widget e.g.:
{"query":{
 "recentchanges":[
 {"type":"new","ns":0,"title":"InfoWidgets\/Advanced guide"},
 {"type":"new","ns":0,"title":"InfoWidgets\/Quickstart guide"},
 {"type":"new","ns":0,"title":"InfoWidgets\/demo.css"},
 {"type":"new","ns":0,"title":"InfoWidgets\/demo.js"},
 {"type":"new","ns":0,"title":"InfoWidgets\/code.js"},
 {"type":"new","ns":0,"title":"InfoWidgets"}
]}}
widget.traversal tells the InfoWidgets how to read a reply like the above. The default value is:
[widget.params["action"], widget.params["list"], "title"]
which - in this case - results with:
["query", "recentchanges", "title"]
The first items in widget.traversal list the names of the objects that have to be traversed to get to the list of answers and the last item is the property to get from that list.
Let's look at an example where you would actually have to specify widget.traversal. This widget will list the ten last editors of the current page:
ar recentEditors = {
 type: 'api',
 params: {
 action: 'query',
 prop: 'revisions',
 rvprop: 'user',
 rvlimit: 10,
 titles: window.wgTitle !== undefined && wgTitle ? wgTitle : ''
 }
}
And the server would reply like this (assuming the current page is this wiki's main page):
{"query":{
 "pages":{
 "1461":{
 "pageid":1461,"ns":0,"title":"Fandom Developers Wiki","revisions": [
 {"user":"Grunny"},
 {"user":"PrakashRaj125"},
 {"user":"Kosmos1209"},
 {"user":"Kosmos1209"},
 {"user":"Kosmos1209"},
 {"user":"Sean Colombo"},
 {"user":"Porter21"},
 {"user":"Grunny"},
 {"user":"Porter21"},
 {"user":"Porter21"}
 ]}}},
 "query-continue":{
 "revisions":{
 "rvstartid":4622
}}}
widget.traversal would have to look like this now:
var pageid = window.wgArticleId !== undefined && wgArticleId ? wgArticleId : 0;
var recentEditors = {
 traversal: ["query", "pages", pageid, "pageid", "user"],
 type: 'api',
 params: {
 action: 'query',
 prop: 'revisions',
 rvprop: 'user',
 rvlimit: 10,
 titles: window.wgTitle !== undefined && wgTitle ? wgTitle : ''
 }
}
== widget.fallback ==
Some queries are bound to come back empty. Trying to show the watchlist of a visitor who isn't logged in e.g. will produce an empty list. You can use this property to provide a link that will be shown instead. The pre-configured watchlist uses Special:UserLogin as fallback.
== widget.error ==
This function is meant for debugging purposes only. It directly patches the error callback from jQuery.ajax through to you. The default function is simply:
error: function () {}
Category:Guides