Extension:Simple Forms

We've needed forms for quite a number of things in our Organic Design wiki such as for creating or editing articles which are based on templates or for making DynamicPageList queries. Instead of making specific code for each form instance, we decided to create a generic set of simple mechanisms which could be re-used to make the creation of all forms and their processing much simpler.

The SimpleForms extension extends the functionality of MediaWiki in two main ways:
 * parser-functions: by adding extra parser functions (accessed using curly-brace syntax in an article's wikitext) which are used for constructing forms and accessing the posted data.
 * index.php parameters: by adding additional parameters to index.php articles can be updated and created directly from parameters passed in links or posted data.

Installation & configuration
This extension is a single script which is included at the end of your LocalSettings.php file as usual. Download the current version from OrganicDesign:Extension:SimpleForms.php and save it in your extensions directory or in a subdirectory to suit the organisation of your extensions.

There are also a number of global configuration variables for enabling, disabling and setting up the various features of the SimpleForms extension. These should be set in your LocalSettings file after the include of the SimpleForms.php script. Here is a description of the valid variables.

Ajax
The SimpleForms extension can use Ajax technology to allow forms or links to work asyncronously (i.e. not involving a page reload). The content in the server's response can be directed to replace a particular portion of the page identified by it's id attribute. SimpleForms uses the Ajax class from the Mootools Javascript framework, which needs to be separately downloaded from mootools.net/download (put a tick in the ajax item near the bottom of the list and then click the download button) and saved in your extensions directory. The $wgSimpleFormsUseAjax global configuration variable must then be set to the relative URL of the location where you have saved the Mootools Javascript framework. Two ways of enabling mootools are provided

1. Your SimpleForms inclusion code in your LocalSettings.php file should then look something like the following example,
 * See Mootools for issues related specifically to using Mootools with MediaWiki version 1.9.x.
 * You may need to change the filepaths to suit your own extension configuration
 * Don't forget to ensure that the Javascript file is readable by the webserver using the URL you've specified, for example on Organic design mootools can be accessed at the URL http://www.organicdesign.co.nz/wiki/extensions/Javascript/mootools.js

2. You may prefer to use Extension:Javascript which loads multiple Javascript files from selected files or directories without duplication. The inclusion code for your LocalSettings.php file would look like the following example if you use Simple Forms and Extension:Javascript together.

Form Syntax & Style
Form syntax is made clearer by using indentation, but it is important to note that whitespace indentation using space characters may lead to undesired results. For this reason, indentation should always be done using tab characters rather than spaces because SimpleForms removes all tabs from the form definition before it gets processed.

Class and id attributes can be added to the #form or #input parser-function syntax, or to surrounding div elements etc to customise form design and layout from your wiki's CSS stylesheet. CSS rules can be added to the MediaWiki:Common.css article rather than editing the CSS file.
 * Ajax links have ajax added to their class attribute so they can be given a specific link style

SimpleForms parser functions
We wanted forms to be created or modified by unprivileged users, so we decided against allowing form articles to use raw HTML and instead added some parser functions, which allow forms to be created, and the posted results captured using normal wikitext notation.

#form
The first parser function is #form which defines the main form container. Three parameters can be supplied, the first two are method and action, which serve the same purpose as usual, except that method can be the name of a javascript function if it's not GET or POST. The third parameter is target which either has the normal meaning, or if the action refers to a function, then the target property refers to a part of the document the result should be sent to.

The JavaScript functions which the form can execute should return a URL (including an optional query-string component) which will then be asyncronously requested from the server using an xmlhttp object. The returned content will replace the content (innerHTML property) of the document element having the id specified in the form's target property.

There's currently just one JavaScript function which is called live, using this as the action of the form requests the URL usign an asyncrounous xmlhttp-POST request and adds all the form's input values to the request.

#input
Form inputs are made with the #input parser function, no JavaScript is allowed in the values, except for names of the functions which are registered in the global $wgJavaScriptFunctions array.

Select-lists and textareas can be created using the #input function with type set to select, textarea rather than having them consuming their own magic.

Input types
In addition to the normal input types list text, image or checkbox, there are the following additional types and properties:

type=select: this is used for dropdown selection lists instead of having a dedicated #select parser function.

type=textarea: this is used for textareas instead of having a dedicated #textarea parser function.

type=submit: this does the same as usual, but can also be combined with method=ajax to make the form submission asyncronous.

type=ajax: the works like a normal input with type=submit which submits the forms except that the submission will occur asyncronously without reloading the page. Add the update parameter set to the id attribute of the element on the page that the results should be rendered in. The Ajax input type also allows a parameter called link which can be set to a URL or article title and causes the input to render as a normal hyperlink instead of as a form button. These link inputs are independent of any form, see 19 June 2007 for a working example of this type of input.

#request
This allows values from the query-string (GET) or POSTed data to be included in the article to be used by other parser functions when calculating or rendering their results. For example, an article could be made something like the following example which would list the items in a category if its been specified, or render a form otherwise.

The form which is rendered also exhibits a DPL query which creates a list of all categories for the dropdown select-list. The #input function expects to have a standard wikitext bullet list supplied for its list of options, so the DPL query sets the mode and listseparators parameters appropriately.
 * Note1: Indenting is optional, but must use tabs not spaces, because spaces at he start of the line cause &lt;pre> sections
 * Note2: This example works, but requires the ParserFunctions and DynamicPageList extensions.

SimpleForms index.php parameters
The SimpleForms extension adds a number of extra parameters to index.php which allows articles to be updated and created directly from HTTP requests without having to process HTML content. Following is an explanation of each of the additional parameters available.

content
The SimpleForms extension offers the ability to specify wikitext content directly in the posted data or query string using the content parameter. This is useful for adding default content to newly created articles, but the main reason we created it was so that forms could use their JavaScript functions to compose wikitext from the form's inputs and then request the parsed result. This effectively allows forms to execute dynamic, transient queries without having to adjust any article content. It's similar to doing a page-preview, but doesn't use any edit form.

The wikitext in the content parameter can be surrounded by a &lt;nowiki> element so that it's easy to assign wikitext queries to it without them being parsed. These nowiki elements will be automatically stripped by SimpleForms when the form is posted.
 * &lt;nowiki> tag usage in the content parameter

If the content parameter is used without any title parameter, then it will be parsed and the result returned without any article being accessed at all by MediaWiki. This feature is used by the search example shown below. If there is a title parameter, but the article doesn't exist, then the article will be created from the content (subject to the $wgSimpleFormsAllowCreate variable). And finally if there is both a content and title parameter and the article does already exist, then what happens to the content depends on the caction (content-action) parameter which is described below.
 * Using content and title together


 * Notes
 * The content query-string item can be used in conjunction with the usual actions, but would usually only be used with action=edit, action=render (or maybe action=raw&templates=expand).
 * Currently the content query-item does not work with action=edit
 * There is a MediaWiki API under development to allow adjustment of content via the request variables inherently, which this extension will make use of when it is ready.
 * Currently friendly URLs in conjunction with the content item (eg. http://www.foo.com/MyArticle?content=SomeWikitext) does not work. So long-form URLs (eg. http://www.foo.com/wiki/index.php?title=MyArticle&content=SomeWikitext) should always be used, but it's advisable to stick with long-form for functional URLs anyway as they're wiki-environment independent.

caction = replace | append | prepend
The content item can be used with another item called caction (content-action) which defines how the content should be incorporated into an existing article specified by the title parameter.
 * replace (default)
 * prepend
 * append

regexp
If the regexp parameter can be set to a PERL-compatible regular expression, an attempt will be made to replace the any matching patterns of text in the article with the content parameter. If there are no matching patterns, then the content will be replaced, appended or prepended according to the caction parameter.

templates = update
This query-string parameter is usually used with action=raw to cause the raw wikitext to have its double-braces (templates, variables and parser-functions) expanded first.

The SimpleForms extension allows the templates parameter to also be used with content. The only applicable value for the templates parameter when used with content is update which causes any templates in the content update their counterpart in the current content. Any template having no match, will be appended. Any having more than one match will cause SimpleForms to try and reduce the matches to a single result by comparing values of the first named parameter. The following table helps to illustrate this. In this example, the content supplied has an unambihuous match with the bar template definition which gets replaced.

In this case the content has been appended because there were no template matches.

''Here all the templates match by name, so an attempt is made to reduce this ambiguous state by comparing the first parameters, in this case the "name" parameter which matches "Jane". The contact entry for "Jane" gets replaced, the phone number has been removed because it was not supplied in the new content. If none of the first parameters matched, the update would be appended to the article as in the previous example.''

''This example shows content to update containing more than one template definition (both the items from the previous two examples). As can be seen, the result is the same as if the two were processed one at a time, i.e. the first updates the "Jane" entry, and the second appends since there's no unique match.''

summary
If a more specific edit summary is preferred to the default, then it can be supplied in this parameter.

minor (not done yet)
If any changes are made, they will be marked as minor edits.

pagename
If the content parameter is used without a title parameter, then the returned page containing the parsed content will, by default, have no title, but if a title for the page is desired it can be set using this parameter. The search-form example below uses this feature to add a "search results" title to the page.

username
If the client is autoauthenticated as being the server (The requesting IP address is one of those contained in the $wgSimpleFormsAllowRemoteAddr array), then it can be changed to a different name by setting this parameter. This allows the server to forward edits to the wiki from other sources and protocols on behalf of the wiki users.

returnto
Set this to an article title that should be returned after processing the request, this is useful if the page being updated is very large and doesn't need to be returned.

action = render
SimpleForms allows the usual MediaWiki render action to also work with special pages. This is very useful as it allows results of special page queries such as Special:DynamicPageList to be used with Ajax requests.

Ajax example
This example renders a form with a dropdown list containing all the categories in the wiki, when one of them is selected and the submit button clicked, an Ajax request is generated which returns a list of all articles in the selected category. This list is then put into the content of a div element below the form. To see the example working, see 18 June 2007 (also 19 June 2007 may be of interest as an example of using ajax links). Here's the wikitext source of the example, 

NO RESULTS TO DISPLAY YET The second hidden value, content contains the DPL query which produces the list of article in the category. The query uses the #request parser-function to obtain the selected category which was posted in the input named cat. Notice that the wikitext of the DPL query has to be enclosed in a &lt;nowiki> so that the unparsed wikitext query can be assigned to the hidden value. After the form content has been posted, SimpleForms will remove the surrounding &lt;nowiki>'s before the content gets parsed.

The last input, with type=ajax works just like a normal submit button, but will work asyncronously using Ajax. the update parameter is used to direct the content of the server response to the element having id of "listcat-result" which is the div below the form.

A user login form
This form example replicates the same form inputs as a normal login form and posts them to the Special:Userlogin page. 

A PayPal donation form
Here's an example which creates a standard PayPal donation form. Update the values to your own paypal-registered email address, and product name. Notice the nowiki tags which are required to protect the URL's from the wiki-parser. 

A form to categorise the current article
This example show how to make a form allowing the user to categorise the current page. When an item is selected from the dropdown list, the form's content and regexp parameters are updated. The regexp parameter is used to prevent more than one occurence of the same category link. If there are no matching category links, then a new one will be appended. To see this example working, go to SimpleForms categorisation example. 

Blog Example
This example allows the user to post comments to an article's talk page using a dynamic Ajax form, see this example in action at Blog example. Comments are posted to the article's talk page dynamically. The talk page is transcluded and a form allows users to enter a heading, their name and a comment which is then dynamically appended to the talk page and the transcluded content updated via an Ajax request. The submit button looks rather complicated, this is because the content being appended to the talk page needs to be composed by the Javascript from the title, name and body inputs. 

Change log

 * Version 0.3.9 (2007-09-03): Bail from processRequest if title is special
 * Version 0.3.8 (2007-09-01): Fixed bug preventing content from updating article when caction=replace
 * Version 0.3.7 (2007-08-29): Use a unique-id for forms instead of counter as forms in ajax requests have conflicting id's
 * Version 0.3.6 (2007-08-29): Remove the sf-prefix by default as it's causing trouble
 * Version 0.3.5 (2007-08-27): Fixed bug preventing content action from being able to create new articles
 * Version 0.3.3 (2007-07-24): Fixed a bug causing action=render to fail when used with content and no title
 * Version 0.3.2 (2007-07-09): Removed special-page and #edit parser-function, SimpleForms will not be implementing these
 * Version 0.3.0 (2007-07-07): Make action=render work with special pages and with article updates
 * Version 0.2.6 (2007-06-28): Patch to allow form-submit to work properly in Extension:Wiklets while they're still iFrames
 * Version 0.2.5 (2007-06-19): regexp parameter added
 * Version 0.2.3 (2007-06-19): content without title works with action=raw (including optional templates=expand)
 * Version 0.2.2 (2007-06-19): action=render added automatically for Ajax inputs, Ajax link inputs done
 * Version 0.2.1 (2007-06-19): Allow &lt;nowiki>'s around content
 * Version 0.2.0 (2007-06-18): added Ajax functionality using MooTools
 * Version 0.1.1 (2007-06-16): returnto parameter added
 * Version 0.1.0 (2007-06-15): templates parameter working
 * Version 0.0.9 (2007-06-11): Rendering of content without associated title working
 * Version 0.0.3 (2007-05-10): Main form and input parser-functions working, ready for basic use

Todo, Bugs & Problems

 * There's a bug which prevents the content parameter from being empty which is a problem if using with regexp to remove matching items.
 * action=render is only working for some special pages (like Special:Version, but not others like allpages or DPL
 * content is not working with edit yet
 * It should use edit tokens, see API for discussion about this.
 * Test ajax with request-prefix
 * "undefinedundefinedundefinedundefinedundefinedundefinedundefined..." appears under edit buttons unless Mootools is disabled - see Mootools
 * Location dependence: there's nothing in the code making in location dependent, and I've tested installing it in multiple locations without issue.