- The Book of Dojo
- Quick Installation
- Hello World
- Debugging Tutorial
- Introduction
- Part 1: Life With Dojo
- Part 2: Dijit
- Part 3: JavaScript With Dojo and Dijit
- Part 4: Testing, Tuning and Debugging
- Part 5: DojoX
- The Dojo Book, 0.4
User Actions
Submitted by criecke on Sat, 11/17/2007 - 14:43.
The problem is our tree does nothing but stand around looking beautiful. Nothing wrong with that. Normally, though, you'd want some kind of actions.
Events
At the very least, you probably want to do something when a user clicks or press [ENTER] on a node. To do this, you can use the onClick event.

Pick a Pop Tart Please
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script>
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.Tree");
dojo.require("dojo.parser");
</script>
</head>
<body class="tundra">
<div id="response">Pick a Pop Tart Please</div>
<div dojoType="dojo.data.ItemFileReadStore"
url="poptarts_direct.txt" jsid="popStore"></div>
<div dojoType="dijit.Tree" store="popStore" labelAttr="name"
label="Pop Tarts">
<script type="dojo/method" event="onClick" args="item">
dojo.byId("response").innerHTML =
"You're a " + popStore.getLabel(item) + " fan, eh?";
</script>
</div>
</body>
</html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script>
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.Tree");
dojo.require("dojo.parser");
</script>
</head>
<body class="tundra">
<div id="response">Pick a Pop Tart Please</div>
<div dojoType="dojo.data.ItemFileReadStore"
url="poptarts_direct.txt" jsid="popStore"></div>
<div dojoType="dijit.Tree" store="popStore" labelAttr="name"
label="Pop Tarts">
<script type="dojo/method" event="onClick" args="item">
dojo.byId("response").innerHTML =
"You're a " + popStore.getLabel(item) + " fan, eh?";
</script>
</div>
</body>
</html>
Alternatively, you can use Dojo's publish/subscribe event system. When a node is clicked, the tree id is sent as the topic along with the message:
- tree: the actual tree widget
- event: "execute"
- item: the dojo.data item selected
- node: the DOM node selected
Drag and Drop
Dojo trees are great, and so is Dojo Drag And Drop (DnD). But together, they're unstoppable! Not being satisfied with our selection of Pop Tarts, we'll create a pool of Drag and Drop sources to add:
<ul dojoType="dojo.dnd.Source">
<li class="dojoDndItem" id="Hot Chocolate">Hot Chocolate</li>
<li class="dojoDndItem" id="Blueberry">Blueberry</li>
</ul>
<li class="dojoDndItem" id="Hot Chocolate">Hot Chocolate</li>
<li class="dojoDndItem" id="Blueberry">Blueberry</li>
</ul>
The user should only be allowed to drop a Pop Tart on its home category - for example, Blueberry should only go under Fruit. To handle this, we use JavaScript regular expressions to make an intelligent guess. We add these to the data store:
{ label: 'name', identifier: 'name', items: [ { name:'Fruit', type:'category', regexp:'.*erry$'}, { name:'Cinammon', type: 'category', regexp:'[Cc]innamon', children: [ { name:'Cinammon Roll', type:'poptart' }, { name:'Brown Sugar Cinnamon', type:'poptart' }, { name:'French Toast', type:'poptart' } ] }, { name:'Chocolate', type: 'category', regexp:'([Cc]hocolate|Fudge)'} ] }
You can download this file below. Next we wire in DnD to the Tree. This is as simple as specifying two attributes: the controller and the acceptance checker extension point, which we'll write shortly.
<div dojoType="dijit.Tree" store="popStore" labelAttr="name"
label="Pop Tarts" jsid="ptTree"
dndController="dijit._tree.dndSource"
checkItemAcceptance="poptartCheckItemAcceptance">
label="Pop Tarts" jsid="ptTree"
dndController="dijit._tree.dndSource"
checkItemAcceptance="poptartCheckItemAcceptance">
The checkItemAcceptance extension point function is called each time a drop target is entered. In Tree's case, every node is a drop target. How do we know it's valid? The function must check the dragged node to the regular expression of the drop node:
function poptartCheckItemAcceptance(node,source) { // Get the associated dojo.data item for the target item = dijit.getEnclosingWidget(node).item; // Need to check for item because when dropping on a root node, // item === null if (! item) return false; ptType = ptTree.store.getValue(item,"type"); if (ptType == 'category') { // We make intelligent guesses about the correct folder re = new RegExp(ptTree.store.getValue(item,"regexp")); okToMove = true; for (var itemId in source.selection) { console.debug(itemId+" tested against "+re.toString()); okToMove &= re.test(itemId); } return okToMove; } else return false; }
So now all the pieces are in place, yielding:

Drag a Pop Tart to Its Category
Hot Chocolate
Blueberry
And here's the full source code, which is downloadable below:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script>
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.Tree");
dojo.require("dojo.parser");
dojo.require("dojo.dnd.Source");
dojo.require("dijit._tree.dndSource");
function poptartCheckItemAcceptance(node,source) {
// Get the associated dojo.data item for the target
item = dijit.getEnclosingWidget(node).item;
// Need to check for item because when dropping on a root node,
// item === null
if (! item) return false;
ptType = ptTree.store.getValue(item,"type");
if (ptType == 'category') {
// We make intelligent guesses about the correct folder
re = new RegExp(ptTree.store.getValue(item,"regexp"));
okToMove = true;
for (var itemId in source.selection) {
console.debug(itemId+" tested against "+re.toString());
okToMove &= re.test(itemId);
}
return okToMove;
}
else
return false;
}
</script>
</head>
<body class="tundra">
<div>Drag a Pop Tart to Its Category</div>
<div dojoType="dojo.dnd.Source">
<div class="dojoDndItem" id="Hot Chocolate">Hot Chocolate</div>
<div class="dojoDndItem" id="Blueberry">Blueberry</div>
</div>
<div dojoType="dojo.data.ItemFileWriteStore"
url="poptarts_dnd.txt" jsid="popStore" />
<div dojoType="dijit.Tree" store="popStore" labelAttr="name"
label="Pop Tarts" jsid="ptTree"
dndController="dijit._tree.dndSource"
checkItemAcceptance="poptartCheckItemAcceptance">
</div>
</body>
</html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script>
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.Tree");
dojo.require("dojo.parser");
dojo.require("dojo.dnd.Source");
dojo.require("dijit._tree.dndSource");
function poptartCheckItemAcceptance(node,source) {
// Get the associated dojo.data item for the target
item = dijit.getEnclosingWidget(node).item;
// Need to check for item because when dropping on a root node,
// item === null
if (! item) return false;
ptType = ptTree.store.getValue(item,"type");
if (ptType == 'category') {
// We make intelligent guesses about the correct folder
re = new RegExp(ptTree.store.getValue(item,"regexp"));
okToMove = true;
for (var itemId in source.selection) {
console.debug(itemId+" tested against "+re.toString());
okToMove &= re.test(itemId);
}
return okToMove;
}
else
return false;
}
</script>
</head>
<body class="tundra">
<div>Drag a Pop Tart to Its Category</div>
<div dojoType="dojo.dnd.Source">
<div class="dojoDndItem" id="Hot Chocolate">Hot Chocolate</div>
<div class="dojoDndItem" id="Blueberry">Blueberry</div>
</div>
<div dojoType="dojo.data.ItemFileWriteStore"
url="poptarts_dnd.txt" jsid="popStore" />
<div dojoType="dijit.Tree" store="popStore" labelAttr="name"
label="Pop Tarts" jsid="ptTree"
dndController="dijit._tree.dndSource"
checkItemAcceptance="poptartCheckItemAcceptance">
</div>
</body>
</html>
Attachment | Size |
---|---|
poptarts_dnd.txt | 450 bytes |
tree2.html | 2.04 KB |
- Printer-friendly version
- Login or register to post comments
- Unsubscribe post
Error in Firefox, Unloadable in IE7
Top demo yields:
"You're a undefined fan, eh?" in Firefox.
IE7 won't even load the page.
DnD
Interesting - is it possible to drag from the tree onto something like a textarea? I would love to use DnD to insert the node label into a textarea.
Thanks!
Josh
Not working widget
i still encounter this old problem
"You're a undefined fan, eh?" in Firefox.
DnD in the last example doesnt even work for me.
Could this be fixed soon ?
drag and drop doesn't work in IE
I am using IE 7, and drag and drop in the final example (http://www.dojotoolkit.org/files/tree2.html) doesn't work at all. This is very surprising since Dojo mentions drag and drop and trees in the same sentence when marketing itself. I hate IE as much as the next guy, but it still has over half of the browsers out there. Can someone please update this example to work in IE?
The first error to fix is the following line, add the var declaration to item. It should look like this: var item = dijit.getEnclosingWidget(node).item; and your "Object doesn't support this action" when hovering over a node should go away.
The error then is "newItem() was not passed an identity for the new item"
reply to DnD not working in IE 7
Hi all, I found a way to fix drag and drop IE. I am running dojo 1.0.2.
Go to dijit\_tree\dndSource.js and replace this line '"name":nodes[i].textContent' with this '"name":nodes[i].innerHTML'
This dosent seem to solve
This dosent seem to solve the problem.
label and identifier different, How to handle ?
my data is like this
var data = {data: {
label: 'name', identifier: 'id',.....
and the drag drop source is like this..
< ul dojoType="dojo.dnd.Source">
< li class="dojoDndItem" id="88" name="Hot Chocolate">Hot Chocolate< / li>
< li class="dojoDndItem" id="66" name="Blueberry">Blueberry< / li>
this adds the node , but shows the label as undefined.
How to handle the drag drop when the the label and identifier is different ??
Someone please help.
Thanks
- Raj
root-node-action
I want to call a javaScript function when the root-node is selected. But all I get is an error: 'item has no properties' in Firebug.
I hope somebody can help.
Thanks
Jens
icons
The IBM usability guys asked to add icons to the tree example; otherwise it gives the impression that you can't drag the tree nodes
=========
Bill Keese
Project Lead (aka BDFL) of Dijit