TWikiAjaxContrib
TWikiAjaxContrib relies on not-yet-released Javascript files. To work with the contrib, download the
TWiki 4.1 prerelease scripts. Put these in directory
pub/TWiki/TWikiJavascripts.
TWikiAjaxContrib provides a convenience wrapper class around Yahoo's Connection Manager
(AJAX).
Goals are:
- To make it possible for plugins and skins to cooperate when dealing with AJAX requests without having to plan the order of processing javascript code (plugin code first or skin/template code first)
- To make AJAX calls easier to write, for instance by simply appointing a target container plus data url
- Be able to fetch HTML, XML or Javascript
- The technique of fetching HTML with asynchronous communication is also known as AHAH
.
- To be able to cache fetched and processed data
- To facilitate error feedback
- To be able to use different styles, for instance by appointing a custom loading indicator
Working with AjaxRequest
The class
twiki.AjaxRequest is located in file
twikiAjaxRequest.js.
Plugins vs. Skins
Wouldn't it be nice if a template could just point to a different HTML element to load the content into?
Imagine the following scenario:
- An imaginary plugin that retrieves search results defines a content container where the fetched HTML will be written to
- An imaginary skin finds a better place for these results. It simply points the request target to its "better" template container.
How would that work?
Normally HTML content is loaded using
load:
twiki.AjaxRequest.load("request id",
{
container:"container id",
url:"url"
});
or, once properties have been set for the request id:
twiki.AjaxRequest.load("request id");
Both container id and url can be set at any time, that is to say: at any place in the code, whether in plugin code or in skin template code.
A number of additional (optional) properties can be set as well, see below at
Table of request properties.
But
load would immediately invoke the loading of the HTML - convenient, but too fast. A better design would be to set the properties for the request and let other code change these if necessary.
So the plugin would use this code:
twiki.AjaxRequest.setProperties(
"SEARCHRESULTS",
{
container:"searchResultsPluginContainer",
url:"results.html"
});
Now the skin sets the loading target to a different container (target) id:
twiki.AjaxRequest.setProperties(
"SEARCHRESULTS",
{
container:"myBetterContainer"
});
And makes sure that no other code can change this target by locking the property container (it can be changed when explicitely released with releaseProperties):
twiki.AjaxRequest.lockProperties("SEARCHRESULTS", "container");
So in case the skin code would be loaded after the template code the template container would be used.
Now the HTML can be loaded and displayed with:
twiki.AjaxRequest.load("SEARCHRESULTS");
View demo Plugins vs. Skins
Page parts / Named Sections
This demo illustrates functionality that is available since TWiki SVN 11890.
A named section from a TWiki topic can be fetched using the url param
section (combined with
skin=text to get clean results).
To fetch the secion named "updates":
var url = "%SCRIPTURL{"view"}%/%WEB%/%TOPIC%?section=updates;skin=text";
twiki.AjaxRequest.load("UPDATES",
{
url:url,
container:"updatesDiv"
});
Documentation about STARTSECTION variable
View demo Named Sections
Caching results
Some content should be loaded only once. For instance, when a twisty is used to display dynamic contents it is not always desirable to reload the content each time the twisty is opened. Instead we want the twisty to close and reopen with the same content.
Use property
cache:true to store the fetched results and display these again with a next request.
Cached contents can be cleared with
twiki.AjaxRequest.clearCache("request_id").
View demo Caching results
Loading indicators
Default loading indicator
Because TWiki files are served along dynamic urls we cannot use a static url for the indicator; instead we create HTML with a path to our own default loading incidator.
twiki.AjaxRequest.setDefaultIndicatorHtml(
"<img src='%PUBURL%/%TWIKIWEB%/TWikiAjaxContrib/indicator.gif' alt='' />"
);
We can retrieve the loading indicator with:
twiki.AjaxRequest.getDefaultIndicatorHtml();
View demo Default loading indicator
Custom loading indicator
Each request can have its own loading indicator. Add it as property to either
twiki.AjaxRequest.setProperties:
var indicatorHtml = "<div style=\"
border:1px solid red;
background-color:yellow;
padding:.5em;\">Loading...<\/div>";
twiki.AjaxRequest.setProperties(
"MY_REQUEST",
{
indicator:indicatorHtml
});
(optionally lock the indicator property)
twiki.AjaxRequest.lockProperties(
"MY_REQUEST",
"container", "indicator");
... or set the indicator property with
twiki.AjaxRequest.load
twiki.AjaxRequest.load(
"MY_REQUEST",
{
url:"my_url.html",
indicator:indicatorHtml
});
We can retrieve the loading indicator with:
twiki.AjaxRequest.getIndicatorHtml("MY_REQUEST");
View demo Custom loading indicator
Processing HTML
The default processing handler is
twiki.AjaxRequest._writeHtml that writes the fetched HTML content in the appointed container.
Assign a custom processing handler with the properties
handler (the processing function) and
scope (the function owner).
The function itself should accept 2 parameters:
inId and
inHtml, and should return the processed HTML so it can be cached.
The processing handler can use several ways to manipulate the incoming HTML:
Wrap fetched HTML in styled container
function handleHtml (inId, inHtml) {
// make all text red
var processedHtml = "<div style=\"color:red;\">" +
inHtml +
"<\/div>";
// update the container
var element = twiki.HTML.setHtmlOfElementWithId(inId, processedHtml);
// return HTML to be cached
return twiki.HTML.getHtmlOfElementWithId(inId);
}
Manipulate HTML node texts
function handleHtml (inId, inHtml) {
// update the container
var element = twiki.HTML.setHtmlOfElementWithId(inId, processedHtml);
// reverse some texts
reverseNodeTextsInList(element.getElementsByTagName('code'));
reverseNodeTextsInList(element.getElementsByTagName('p'));
// return HTML to be cached
return twiki.HTML.getHtmlOfElementWithId(inId);
}
Style HTML nodes
function handleHtml (inId, inHtml) {
// update the container
var element = twiki.HTML.setHtmlOfElementWithId(inId, processedHtml);
// style list elements
var attributes = {
"class":"twikiSmall twikiGrayText",
"style":
{
"color":"#fff",
"background-color":"#444"
}
};
twiki.HTML.setNodeAttributesInList(element.getElementsByTagName('ul'), attributes);
// return HTML to be cached
return twiki.HTML.getHtmlOfElementWithId(inId);
}
All three ways are illustrated in the demo.
View demo HTML processing
XML Data handling
Loading ready HTML is the easiest use of TWikiAjaxContrib as it requires no data processing. But if you want to harness
Web Services
you will most likely encounter XML data. To interpret and convert XML to HTML you will need a processing handler.
Assign a custom processing handler with the properties
handler (the processing function) and
scope (the function owner).
The function itself should accept 2 parameters:
inId and
inHtml, and should return the processed HTML so it can be cached.
To fetch XML instead of HTML, give property
type the value
"xml" (by default
type is
"text").
twiki.AjaxRequest.setProperties(
"CITY_DATA",
{
url:"city_data.xml",
handler:"processCityData",
scope:this,
type:"xml",
container:"cityContainer"
});
function processCityData (inId, inXml) {
// process inXML data
// convert to HTML
// write to container with id inId
}
function showCityData () {
twiki.AjaxRequest.load("CITY_DATA");
}
See also:
Ajax programming
(Wikipedia)
View demo XML data handling
Sending data with POST
To send information with
POST, set properties
method and
postData:
twiki.AjaxRequest.load(
"SEARCH_DATA",
{
container:"searchResults",
url:"%SCRIPTURLPATH{search}%/%INCLUDINGWEB%/%INCLUDINGTOPIC%",
method:"POST",
postData:queryString
});
View demo Sending data with POST
Fetching javascript
Javascript code
If a page you are fetching contains javascript, you must load the javascript code separately.
This is illustrated in the
Named Sections demo, where the fetched page section contains javascript calls to code on that same page. The javascript code will not work when fetched in the usual way.
The solution is to create a separate request for the script section:
var javascriptUrl = "%SCRIPTURL{"view"}%/%TWIKIWEB%/WebTopicCreator?skin=text"
+ ";section=javascriptfunctions";
twiki.AjaxRequest.load("NEWTOPICFORM_JS",
{
url:javascriptUrl,
type:"script"
});
The fetched code will be attached to the head node of the DOM.
View demo Named Sections
Javascript files
You can also load javascript files directly. A javascript file request is actually not sent using the
XMLHttpRequest object, but attached to the head node directly. Retrieval is often very fast!
To load a script file, use
type:"scriptfile":
var url = "%PUBURL%/%WEB%/TopicWithScript/showAlert.js";
twiki.AjaxRequest.load("LOADSCRIPT",
{
url:url,
type:"scriptfile"
});
Dealing with failure
Use a 'fail' handler to give feedback when loading of a request should fail.
The fail handler is defined by properties
failHandler and
failScope.
failHandler receives 2 parameters:
inName and
inStatus.
A fail handler may look like:
function handleFailed(inName, inStatus) {
var html = "<div style=\"background:#ffc; padding:.5em;\">" +
"Could not load contents. Please try again later." +
"<\/div>";
twiki.HTML.setHtmlOfElementWithId("failureContainer", html);
}
This handler is set using:
twiki.AjaxRequest.setProperties(
"FAILURE",
{
failHandler:"handleFailed",
failScope:this
});
View demo Dealing with failure
Usage
The Yahoo! classes are available as Contrib at
TWiki:Plugins.YahooUserInterfaceContrib
.
Include the required scripts:
<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/YahooUserInterfaceContrib/build/yahoo/yahoo.js"></script>
<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/YahooUserInterfaceContrib/build/connection/connection.js"></script>
<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikilib.js"></script>
<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikiArray.js"></script>
<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiAjaxContrib/twikiAjaxRequest.compressed.js"></script>
It is recommended to use
TWiki:Plugins.BehaviourContrib
for interface elements:
<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/BehaviourContrib/behaviour.compressed.js"></script>
Public API
twiki.AjaxRequest has these public methods:
-
twiki.AjaxRequest.load = function(inName, inProperties)
-
twiki.AjaxRequest.stop = function(inName)
-
twiki.AjaxRequest.setProperties = function(inName, inProperties)
-
twiki.AjaxRequest.lockProperties = function(inName)
-
twiki.AjaxRequest.releaseProperties = function(inName, inPropertyList)
-
twiki.AjaxRequest.clearCache = function(inName)
-
twiki.AjaxRequest.getDefaultIndicatorHtml = function()
-
twiki.AjaxRequest.setDefaultIndicatorHtml = function(inHTML)
Table of request properties
Properties that can be passed to a request:
| Name |
Description |
Type |
Default value |
container |
id of HTML content container |
String |
none |
url |
URL to fetch HTML from |
String |
none |
handler |
Name of function to process the response data |
String |
_writeHtml (private method) |
scope |
Owner of handler |
Object |
twiki.AjaxRequest (singleton) instance |
failHandler |
Name of function to process the response data in case of failure |
String |
_defaultFailHandler (private method) |
failScope |
Owner of failHandler |
Object |
twiki.AjaxRequest (singleton) instance |
type |
Type of response data: text (text), XML (xml), javascript code (script) or javascript file reference (scriptfile) |
String |
text |
cache |
Cached state of response data |
Boolean |
false |
method |
Method of sending data: GET or POST |
String |
GET |
postData |
Data to send with a POST request |
String |
none |
indicator |
Loading indicator - HTML that will be displayed while retrieving data; can be a custom indicator for each request |
HTML |
none |
Examples
See
TWikiAjaxContribExamples
Settings
- Set SHORTDESCRIPTION = javascript wrapper class around Yahoo's Connection Manager connection.js (AJAX) class
- Set STUB = TWiki::Contrib::TWikiAjaxContrib
Installation Instructions
- Download the ZIP file from the Plugin web (see below)
- Unzip
TWikiAjaxContrib.zip in your ($TWIKI_ROOT) directory. Content: | File: | Description: |
data/TWiki/TWikiAjaxContrib.txt | |
data/TWiki/TWikiAjaxContribExamples.txt | |
lib/TWiki/Contrib/TWikiAjaxContrib.pm | |
pub/TWiki/TWikiAjaxContrib/twikiAjaxRequest.js | |
pub/TWiki/TWikiAjaxContrib/twikiAjaxRequest.compressed.js | |
pub/TWiki/TWikiAjaxContrib/indicator.gif | |
pub/TWiki/TWikiAjaxContribExamples/test_hamlet.html | |
pub/TWiki/TWikiAjaxContribExamples/test_cities.xml | |
- Optionally, run
TWikiAjaxContrib_installer to automatically check and install other TWiki modules that this module depends on. You can also do this step manually.
- Alternatively, manually make sure the dependencies listed in the table below are resolved.
| Name | Version | Description |
|---|
| TWiki::Plugins::BehaviourContrib | >=1.000 | Required |
| TWiki::Plugins::YahooUserInterfaceContrib | >=1.000 | Required |
Contrib Info
Related Topics: TWikiPreferences