How to write a JavaScript to display data in a Semantic MediaWiki

MediaWiki is a powerful tool, and with Semantic MediaWiki, you can do some quite fancy bits, but what if you have that perfect idea for how to display the data in a way that makes sense to users, but you just need to massage the information a little bit (or a lot) to make it look appealing, more interactive, or to support connection between sites. That is what this article aims to do.

[This page is currently a work in progress, please feel free to contribute]

Making your scripts accessible to a site
It is easy to embed code in MediaWiki:Common.js, although this facility is being deprecated. Because of limitations with this solution, we will skip this option completely, for our example we will use the Widgets extension. There is also the option of using the ResourceLoader.

More information on this can be found under Developing with ResourceLoader

High level flow
[Not tested yet, a starter for ten, based on the writers limited]  As you may have realized by now, MediaWiki does not allow you to run JavaScript straight on a page, while all the reasons and thinking for MediaWiki's design decision is outside the scope of this article, there are good reasons, mostly about security.



To the right you can see (a over simplified) version showing the differences between a standard webpage and mediawiki or Semantic Mediawiki server serving up a webpage. What we will work on is the three green boxes. I.E how to store, create hook and call our javascript. We will then run a SMWAPI call which, when working, should display a red box just over this text explaining about the security issue. Please note, for security, only administrators are allowed to add custom java code to wikipedia. As such, to use this article to write a small javascript you will need administrator rights to the media wiki.[will need to be discussed with SMW admins weather or not they would allow us to add a custom java function for this article]

Storage
The first thing we need to do is create somewhere to store the javascript. One option would be to store it in MediaWiki:commons.js which would make it available to all pages within the mediawiki. However, to keep things clean, we only want our code to be available on the pages which will use it, so we need some kind of container.

The way we will do this is by creating a widget using the Mediawiki:Widgets extension. The Widgets extension allows the creation of raw HTML pages that can be embedded (similarly to templates) in normal wiki pages. It does mean that we will need to work with the code as a html page with javascript and css embedded rather than a pure javascript and css files, but it still meets our requirements.

Now its time to see if we can get it to write something. Go to the mediawiki, and the page .../index.php/Widget:Test (You should be told that the page does not exists, so click edit).

In the editor window write the following code:

Once you save and exit, you should now see the actual code on the Widgets:Test

Creating our hook
So now we have the code in our widget, the next step is simple. Create a new wikipage, and enter the following code. Once you save and edit, you should see a page with the text "I Wrote Something!!!". If this is the case, success, we have stored some code in a safe manner.

However, this isn't enough is it. For this to be useful we need to send it some information while we are at it as well, and read some standard variables. We will be sending two variable to our widget, warning and red. Due to how Widgets manages variables, we want to set them as part of the call rather than just sending the data.

What we mean by that is, often when you call a object or function, the function will be responsible to interpret and manage the data sent with the call, where as with Widgets, any data will be interpreted by default as a request to set a variable with that name to true. Nice for web coding but not how we want to use it.

For the hook we will add a text and a color variable.

We will also need to add some new commands to our script

If your screenshot of your test wiki page looks like the picture to the right, you are doing it right

Talking to the Smarty(pants) Template Engine
Widgets uses the smarty Template Engine (the pants addition is just the writers sense of humour). To understand its role we will quickly cover what happens when we put code in a widget. [This is based on the authors understanding, please confirm correctness]

In short,the code in the widget will then be lifted and rendered into a php file (have a look in compiled_templates) prior to being stored as a precompiled template in the database.

The Smarty manage things like translation of variables. The four codes we use above are:

Basically, this block of text will be used if anyone navigates to the widget, good idea is to pur some kind of instructions for the user.

[Author thinks this is to avoid having a table of content rendered]

This is where we put the code that will be inserted when the wikipage calls

This is all Smarty, and to resolve the problem of server memory space not available for client side code. What will happen is that during compilation Smarty will replace this section by whatever is in $text at the time. While there is a rather extensive manual at [ http://www.smarty.net/docs/en Smarty.net ], I have not been able to find a good manual for how to use it with MediaWiki and Widgets.

At this point, we have completed the three first three green boxes.

Widget:Showwarning, a useful example
We will be doing one last thing before we move on to the API calls. We will update our code to do the following

To create the Widget Showwarning (just go to Widget:Showwarning) and enter the following code:

To call our new code, we need to change the wiki somewhat, as we will need a div id which matches the id we send to our Widget. The code we will use is:

If done right, and I did not forget any steps, you should see something along the lines of the screenshots to my right, and isn't that box all pretty.

Create some data to retrieve
So, we can now display a textbox using our wanting, but we want to move one step further, we want to use SMW data to decide what we put in our box. For this we will create a Usermessages page as a standard MediaWiki (with Semantic extension) page, so go to /index.php/Usermessages edit and type in. If we now go to SMW special page "Special:Browse/Usermessages" you should be able to see our two messages as per the screenshot. We can now also ask the API for this information. . Now we get the following back. In the business, this is what we would call our "Bobs your uncle" moment. We got data in JSON format, and it is almost like javascript was written to use data in JSON format, so we just need to make a call to that address, then get a function to get the message we want. There are nicer ways, and there are further examples of other API's below, but for us, this is all we need for our little app.

Showmessage to use JSON return
So as a last step. We now want to get our javascript to use the JSON data to identify the warning message we have seen. To do this we need to complete the following steps.

Get Jquery to do the JSON call for us (already built into mediawiki) step through the JSON data until we find a message matching our criteria (we have both a Hello and a Warning now) Move our HTMLinner commands into the return function for the JSON call (otherwise we'll end up writing the message before we have retrieved it) Massage the data a bit to drop the underscores in favour of space

And now we have succeeded, we can run our javascript, for any client who opens our page, and provide our script with information from the SMWapi as promised.

How to clear precompiled templates from database/cache
[Author have no clue, but needs to be answered. For now only way is to create a template widget with a new name (say test2) to force the widget to update]

''There is a potential work around for this issue, update the call, ie, change the colour to blue in the  call. Due to how the caching and Smarty works with hardcoded variables, any change to the options to send will force Widget to be recreated. ''


 * &lt; is not the same as <

Basically, mediawiki by default have methods for avoiding people to put scripts and unknown/unsafe hooks on pages, as such, the way it "disarms" code is changing control characters to ASCII codes, looks the same but with a different meaning. The way to write a HTML ASCII code is &#38;#ASCIICODE or &#38;#CODE, so basically, when you put in  it is translated to ASCII codes as , making certain your browser will not identify the HTML tag.


 * Turn of that fancy editor

If you have a rich text editor enabled, it might be worth turning it off in user preferences-> Editing for the user you use for development, as some of those editors tries to "clean" up the text, including "disarming" code.


 * Write access to compiled_templates with SELinux

Widgets gets really upset if they can't be written to the compiled_templates directory. If you use CentOS or other SELinux enabled Linux distro, the answer is to run. In needs root access to probably one for your sys admin if its not clear what this means.

Options to access via API
There where a lot of people who contributed to this article, and especially providing links for additional readings on API. We picked the easiest option for what we where doing, but if you need further functionality from the API, or just want to look at other options, these where some of the ones that where suggested.

MediaWiki's ResourceLoader
Resource registration via MW's ResourceLoader can happen within the PHP source using  or internally via JavaScript itself.

JavaScript modules
Testability and readability should be considered when writing a JavaScript module and to encourage such virtues using namespaced modules (opposed to littering the global $ namespace) is one way to improve maintainability. For an example have a look at ext.srf.boilerplate.namespace.js.

Using SMWAPI
Register the  dependency with the ResourceLoader.

Examples for the use of the /  can be found in ext.srf.formats.eventcalendar.js and ext.srf.formats.datatables.js

Using MWAPI (with JQuery)
Later versions of Javascript (possibly using polyfills for compatibility) obviate the need for JQuery, but may as well use it since it's built in.

Contributing to this article
Edit the page.