The Dijit ContentPane is a basic layout widget that gives you the ultimate
in control over your dynamic Web content. You can update the content inside
one of these panes via the content
or href
properties as well as attach
code to various callback functions. Not to be confused with iFrames, which only
supports document fragments, the ContentPane can hold just about anything, including
widgets and even other ContentPanes. It can be used by itself, but it is often
found as a child of other containers such as LayoutContainer, SplitContainer,
or TabContainer. Today's article will give you a starting point for loading
dynamic content using ContentPanes.
A Simple Dijit ContentPane Example
In the following code, a declaratively created ConentPane loads the content.html
page using the href
attribute. ContentPanes are commonly defined by a <DIV>
element. To parse the widget, the djConfig
's parseOnLoad
attribute must be set
to true
and the DIV's dojoType
attribute set to dijit.layout.ContentPane
:
Here is the markup for the content page:
content.html
file is retrieved using Ajax, so it must reside on the same
server as the containing page. Built-in security constraints prevent Ajax from
fetching documents from another server! Unfortunately, Dojo doesn't just come
out and say it. Instead, you'll receive an error like the following:
Error: [Exception... "'Permission denied to call method XMLHttpRequest.open'
when calling method: [nsIDOMEventListener::handleEvent]" nsresult: "0x8057001e
(NS_ERROR_XPC_JS_THREW_STRING)" location: "
"Permission denied to call method XMLHttpRequest.open" is the key phrase to look for.
While the content loads, a generic "Loading..." message is displayed.
You can overwrite it using the loadingMessage
property.
Calling JavaScript Functions from Within a ContentPane
There are two script types that you can include within the ContentPane <DIV>
tags to associate a JavaScript code block to the enclosing object: dojo/method
and dojo/connect
. In the Event Listening Made Easy with Dojo.connect
article, I mentioned how including script blocks in this fashion has the advantage
of setting the this pointer to the object. Including a script block with the
type of dojo/method
will execute it much like the postCreate()
would with programmatically
created widgets. As such, it's a good place to do some initializing:
Connecting to Special ContentPane Events
To give you more dynamic control over the ContentPane, it provides a few special
events. When content is loaded through the href
property, a number of callbacks
are available which can be configured. These are executed at different phases
of the loading process:
- onDownloadStart: Called before the download of the content begins.
- onDownloadEnd: Called when the content has completed loading.
- onDownloadError(error): Called if there was an error with the download.
To connect to events, set the script type
to dojo/connect
. The following code
snippet demonstrates the event order and includes the useful onLoad()
and onUnload()
widget events:
The above code logs the events as they occur, with the exception of onDownloadError()
,
because none were encountered, and onUnload()
, which has not yet fired.
It executes when you replace the pane content, navigate away from the page,
or close the browser. Here is the code output:
This is the content.html page.
The contentPane is ready.
The contentPane has begun downloading.
The contentPane has begun loading.
The contentPane has finished downloading.
Programmatic Creation
Of course, anything you can do declaratively in Dojo, you can do programmatically as well...maybe even better! Here's some code that creates a new ContentPane when the page first loads and assigns HTML markup to the content property (twice in fact!):
Forget about using
any download events when setting the content. They only work with the href
property,
as they should!