A common use case for DHTML/ajax is to fetch a fragment of html using XHR or some other way, and change the innerHTML of a div with that content. Problem with this is that it doesn't instanciate widgets and doesn't fire scripts. ContentPane was created to make widgets and scripts work and reduce the potential for memory leaks. ContentPane is a base widget for many (Html)widgets, it handles remote loading as well as local setting of content and instanciating widgets in that content. Think of it as islands in your page that can easily switch content using setContent() or setUrl().
Many other widgets inherits ContentPane, like Tooltip, Dialog, FloatingPane etc. That means that all the methods and properties of ContentPane also applies to them.
ContentPane is often used as children of Layout widgets like LayoutContainer, TabContainer, AccordionContainer
Dont misstake it for a Iframe though, It should not be used on very large html fragments.
Simple usage ... <div id="cpane" dojoType="contentPane" href="initialContent.html"><div> <a href="javascript:dojo.widget.byId('nextContent.html')">Goto nextPage</a> ...
Basic options
Methods apart form those provided by ContentPane's superclass HtmlWidget
Methods (Intended as event hooks using dojo.event.connect)
In order to prevent the default messages you can do something like this:
<script>
var myLoadMessage = {
show: function(event){
event.preventDefault();
... custom code here
},
hide: function(){...}
}
dojo.addOnLoad(function(){
var pane = dojo.widget.byId('myPaneId');
dojo.event.connect(pane, "onDownloadStart", myLoadmessage, "show");
});
</script>
<div dojoType="ContentPane" id="myPaneId">...startcontent...</div>
or
<div dojoType="ContentPane"
onDownloadStart="myLoadMessage.show(arguments[0]);">...startcontent...</div>
When used as a child to TabContainer, AccordionContainer or PageContainer TabContainer, AccordionContainer or PageContainer extends Widgets with these extra options
When used as a child of LayoutContainer LayoutContainer package extends Widgets with this option
FAQ
<script>
var i = 0;
function addToI( j ){
i = i + j;
return i;
}
</script>
becomes (from window scope):
(function( ){
var i = 0;
function addtoI( j ){
i = i + j;
return i;
}
})
<script>
i = 0; // note lack of var
addToI = function( j ){ // we could also do window.addToI = function( j ){ ...
i = i + j;
return i;
}
</script>
becomes (from window scope)
i = 0;
function addtoI( j ){
i = i + j;
return i;
}
<script>
this.i = 0;
this.addToI = function( j ){
this.i = this.i + j;
return this.i;
}
</script>
becomes (from window scope)
(function(){
this.i = 0; // now it is a property of this function and can be reached from the outside.
this.addToI = function( j ){
this.i = this.i + j;
return this.i;
}
})
var added = dojo.widget.byId('myPaneId').scriptScope.addToI( 10 );
dojo.debug(added) // prints 10
added = dojo.widget.byId('myPaneId').scriptScope.addToI( 10 );
dojo.debug(added); // prints 20
and so on...
Now lets say we have html that would like to alert the value of i (this.i) in plain html that would be:
<button onclick="alert(i);">Tell me i !</button> // As explained above this wont work in ContentPane(unless you set it to global by omitting var).Now if we now the ID of the contentPane that pulls in this content we could do:
<button onclick="alert(dojo.widget.byId('myPaneId').scriptScope.i);">Tell me i !</button>
// this will work in ContentPane
That is'nt very useful as we don't always know the ID of the contentPane that pulls in the html when we write the content.
<button onclick=" scriptScope.i">Tell me i !</button> // this will work in ContentPane // NOTE: Due to a bug in ContentPane 0.3.1 you need to add a extra space before the keyword // Thank you Sasha Firsov for finding that!The parent scope of scriptScope is window, the reason for that is to avoid messing with widget internals. Just imagine the disaster a redefinition of setUrl function would cause otherwise.
... some content <div dojoType="DatePicker" id="myPicker"></div> ... rest of contentA content script could look like:
<script>
var o = {
storeDate: function( ){
var datePick = dojo.widget.byId('myPicker');
var date = datePick.storedDate;
// save date somewhere
}
};
_container_.addOnLoad(function(){
var picker = dojo.widget.byId('myPicker');
dojo.event.connect(picker, "onSetDate", o, "storeDate");
});
// remember to disconnect onUnLoad, very important!!
_container_.addOnUnLoad(function(){
var picker = dojo.widget.byId('myPicker');
dojo.event.disconnect(picker, "onSetDate", o, "storeDate");
});
</script>
<html>
<head>
<script>
var djConfig = {isDebug: true};
</script>
<script src="dojo/dojo.js"></script>
<script>
var scriptScope = this;
if(typeof _container_ == 'undefined'){
var _container_ = dojo;
}
_container_.addOnLoad(function(){
dojo.debug("Successfully loaded!");
});
this.doWhenClicked = function(txt){
dojo.debug(txt);
}
</script>
<body>
<a href="javascript:scriptScope.doWhenClicked('You clicked a link!');">Click here!</a>;
</body>
</html>
*********Your mainpage***********
<html>
<head>
<script src="dojo/dojo.js"></script>
<script>
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.widget.LayoutContainer");
function changeUrlInClient(url){
var client = dojo.widget.byId("client");
client.setUrl(url);
}
</script>
</head>
<body>
<div dojoType="LayoutContainer" layoutChildPriority='none' style="border: 1px solid blue; width: 800px; height: 300px;">
<div dojoType="ContentPane" layoutAlign="left" style="width: 200px;" executeScripts="true" href="linkpage.html"></div>
<div widgetId="client" dojoType="ContentPane" layoutAlign="client" style="border:1px solid red;"></div>
</div>
</body>
</html>
*******linkpage.html************
<html>
<head>
<script>
var o = {
listen: function(evt){
// if the onclick came from a
</head>
<body>
<a href="content1.html">content1</a>
<a href="content2.html">content2</a>
<a href="content3.html">content3</a>
<a href="content4.html">content4</a>
</body>
</html>
**********mainpage************
<html>
<head>
<script src="dojo/dojo.js"></script>
<script>
dojo.require("dojo.widget.FloatingPane");
dojo.require("dojo.widget.Button");
</script>
</head>
<body>
<div dojoType="FloatingPane"
title="Login example"
style="width: 300px; height: 300px;"
executeScripts="true"
cacheContent="false"
href="login.php">
</div>
</body>
</html>
*********login.php**********
<?php
session_start();
// are we trying to login?
if(isset($_GET["login"])){
// this could of be a database instead
$users = array(
"JohnDoe"=>
array("pass"=>"foo", "id"=>1),
"JaneDoe"=>
array("pass"=>"bar", "id"=>2),
"JuniorDoe"=>
array("pass"=>"baz", "id"=>3)
);
if(isset($_POST["user"]) && isset($_POST["pass"])){
$pass = $_POST["pass"];
$user = $_POST["user"];
if(isset($users[$user]) && ($users[$user]["pass"] == $pass)){
$_SESSION["id"] = $users[$user]["id"];
exit("(true);");
}
}
//if we get here we have failed to login
exit("(false);");
}
// logout?
if(isset($_GET["logout"])){
unset($_SESSION["id"]);
}
if(isset($_SESSION["id"])){
// it is safe to show secret content
?>
<script type="text/javascript">
this.logout = function(){
_container_.setUrl("login.php?logout=true");
}
</script>
<h3>You have successfully logged in!</h3>
showing secret content here
<a href="#" onclick="scriptScope.logout();">log out</a>
<?php
}else{
//no it wasnt safe, show our login script
?>
<script type="text/javascript">
this.ok = function(){
_container_.domNode.style.cursor = "wait";
dojo.io.bind({
formNode: dojo.byId("login"),
mimetype: "text/javascript",
handler: function(type, data){dojo.debug(data);
_container_.domNode.style.cursor = "";
if(type=="load"){
if(data){
_container_.setUrl("login.php");
}else{
dojo.byId("message").innerHTML = "Wrong username or password";
}
}else{
dojo.byId("message").innerHTML = "An error occured while login, please try again.";
}
}
});
}
this.quit = function(){
_container_.hide();
}
</script>
<form name="login" id="login" method="post" action="login.php?login=true">
<div id="message" style="text-align:center; color: red;">You need to login</div>
<label for="user">Username:
<input type="text" name="user"/>
<label for="pass">Password:</label>
<input type="password" name="pass"/>
<button dojoType="Button" onClick="scriptScope.ok();"/>login</button>
<button dojoType="Button" onClick="scriptScope.quit();">quit</button>
</form>
<?php
}
?>
<html>
<head>
<script src="dojo/dojo.js"></script>
<script>
dojo.require("dojo.widget.ContentPane");
</script>
</head>
<body>
<div dojoType="ContentPane" >
<script>
// this script will fire before dojo makes our parent a ContentPane widget, so it wont be
// affected by executeScripts at all.
// i wont have a _container_ variable and scriptScope wont hide any variables
// it will work just as a inlne javascript block always has
alert("This alert will fire event if you have executeScripts=false");
</script>
</div>
</body>
</html>