Posted in Dojo Cookies | Tutorials | Intermediate
Extending dojo.dnd with a creator function
Following the Dojo philosophy of “build with, not on”, dojo.dnd
provides a terrific API for getting the right behaviour for your app, with plenty of extension points and monkeypatching opportunities. Making a creator
function for dojo.dnd.Container
is the most obvious way to customize dojo.dnd
, because it gets called anytime a container or avatar wants to visualize a data item.
The creator
is called for two events:
- When an item is added to a container (at startup, or when dropped).
- When an item is dragged out of its container, creating an avatar.
The avatar represents dragged items visually, and is typically a scaled-down version of the item.
The callers expect the creator function to return an object containing node
, data
, and type
members, though the type
is not strictly necessary. The node
will be rendered on a page, while data
is only used internally as the input to creator
.
// creator: Function: a creator function, which takes a data item, and // returns an object like that: // {node: newNode, data: usedData, type: arrayOfStrings}
The DnD system calls your creator function with a piece of data, and possibly a String hint
, and it’s up to your function to return a new object. The interpretation of the data is particular to your app. In this example the input is either a String
or an Object
, so we’ll have to handle both cases.
creator: function(/*Object|String*/ item, /*String?*/ hint){
When an item starts getting dragged, the function will be called to make an avatar, so the hint
parameter will equal "avatar"
. The first thing my creator checks is if the DnD system wants an avatar:
if(hint == "avatar"){ return {node: dojo.dnd._createSpan(item.domNode.innerHTML)}; }
In this case, I know the item
is an object with an attached DOM node, so I send the innerHTML
to the _createSpan
helper function. The DnD system takes care of the rest.
If we’re not being asked for an avatar, then we want to create a real node to insert into a container. The item is a string if it’s coming from a certain source in my app, but I want to turn it into an object before it goes into this container.
else if(typeof item == "string"){ item = turnIntoObject(item); }
The turnIntoObject
function finds the right constructor, does a bit of setup, and returns a new object corresponding to the string.
Finally, we know we’re not creating an avatar and our item
is an object, so we can return the object that the DnD system expects: {node: ..., data: ...}
. To make life easy, I pass the current item
object into the data
slot, so next time we’ll drop straight through to this return
.
return {node: item.domNode, data: item}; // Object }
And here’s the function in one piece:
// creator: Function: a creator function, which takes a data item, and // returns an object like that: // {node: newNode, data: usedData, type: arrayOfStrings} creator: function(/*Object|String*/ item, /*String?*/ hint){ if(hint == "avatar"){ return {node: dojo.dnd._createSpan(item.domNode.innerHTML)}; }else if(typeof item == "string"){ item = turnIntoObject(item); } return {node: item.domNode, data: item}; // Object }
Tags: dojo.dnd