<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3810921673000177425</id><updated>2011-11-27T18:15:02.865-06:00</updated><category term='dojo'/><title type='text'>neonstalwart</title><subtitle type='html'>there's a loose nut on the end of this keyboard</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-770160540775980220</id><published>2010-04-02T09:51:00.004-05:00</published><updated>2010-04-02T10:05:52.867-05:00</updated><title type='text'>firefox setTimeout lateness argument</title><content type='html'>dijit.Dialog uses an animation when you hide it.  because of this, if you want to destroy the dialog after hiding it, you have to use a setTimeout to let the animation finish before you destroy it.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;    setTimeout(dojo.hitch(dlg, 'destroyRecursive'), dijit.defaultDuration);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;you would expect this to simply destroy the dialog and any content it contains.  however, i was finding that sometimes, the domNode still remained after destroying the dialog.&lt;br /&gt;&lt;br /&gt;after some quick debugging, i was seeing that destroyRecursive was being passed an integer as it's first parameter.  destroyRecursive has an option to provide a preserveDom parameter and it will preserve the dom and so it was interpreting this integer as my intention to have the dom preserved.  this was not my intention, so where was this integer coming from?&lt;br /&gt;&lt;br /&gt;i headed straight to mozilla developer center and took a look at the docs for setTimeout.  it turns out that firefox passes a &lt;a href="https://developer.mozilla.org/en/DOM/window.setTimeout#.22Lateness.22_argument"&gt;lateness argument.&lt;/a&gt;  you can see this happening with this snippet of code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;    setTimeout(console.log, 100);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;in my case, to make sure that the destroyRecursive function was doing what i intended it to do, i had to explicitly provide the first parameter via dojo.hitch&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;    setTimeout(dojo.hitch(dlg, 'destroyRecursive', false), dijit.defaultDuration);&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-770160540775980220?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/770160540775980220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=770160540775980220' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/770160540775980220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/770160540775980220'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2010/04/firefox-settimeout-lateness-argument.html' title='firefox setTimeout lateness argument'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-629053179544942579</id><published>2009-11-21T18:48:00.023-06:00</published><updated>2009-11-21T22:52:31.703-06:00</updated><title type='text'>working with dijit.form.Form</title><content type='html'>i've found myself using this kind of pattern lately and found that i've also been explaining it quite often as well.  so to avoid any further explanations here's some of what i've learned about how to try and design your code to leverage what dijit.form.Form (and other widgets) can provide.  NOTE: my examples are based on dojo 1.3.2 and there are small variations to be made if you use dojo 1.4 (which is almost ready for release).  the principles remain the same.&lt;br /&gt;&lt;br /&gt;i'm going to cover:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;how to set and get values for forms and form widgets&lt;/li&gt;&lt;br /&gt;&lt;li&gt;creating widgets to help with using complex data&lt;/li&gt;&lt;br /&gt;&lt;li&gt;widget templating including dojoAttachPoint and dojoAttachEvent&lt;/li&gt;&lt;br /&gt;&lt;li&gt;and more...&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;dijit setters and getters&lt;/h2&gt;&lt;br /&gt;dojo's widget library (dijit) provides a uniform way to set and get properties of widgets.  this is provided by the dijit._Widget base class and it used like so:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;    var widget = new SomeWidget();&lt;br /&gt;    &lt;br /&gt;    // get the value property of the widget&lt;br /&gt;    widget.attr('value');&lt;br /&gt;&lt;br /&gt;    // set the value property of the widget&lt;br /&gt;    widget.attr('value', 'a new value');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the &lt;code&gt;.attr&lt;/code&gt; function makes it convenient to be able to consistently set or get properties.  there's basically 3 ways that it works.  i'll explain 2 of them - the 3rd way is also very powerful and makes use of the attributeMap to map widget properties to node properties.&lt;br /&gt;&lt;br /&gt;first, &lt;code&gt;.attr&lt;/code&gt; looks to the widget for some specially named functions to help with setting/getting properties.  the naming convention is that if you're working with property &lt;code&gt;foo&lt;/code&gt; then you can define a function called &lt;code&gt;_setFooAttr&lt;/code&gt; which will be called in response to &lt;code&gt;widget.attr('foo', value);&lt;/code&gt; and you can define a function called &lt;code&gt;_getFooAttr&lt;/code&gt; which will be called in response to &lt;code&gt;widget.attr('foo');&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;the &lt;code&gt;_setFooAttr&lt;/code&gt; function will be passed the 2nd parameter of &lt;code&gt;widget.attr('foo', value);&lt;/code&gt; and &lt;code&gt;_getFooAttr&lt;/code&gt; should return a value to represent the &lt;code&gt;foo&lt;/code&gt; property.&lt;br /&gt;&lt;br /&gt;the 2nd option that &lt;code&gt;.attr&lt;/code&gt; will use, is it will directly update/read the property eg. &lt;code&gt;widget.attr('foo', value)&lt;/code&gt; is the same as &lt;code&gt;widget.foo = value;&lt;/code&gt; and &lt;code&gt;var value = widget.attr('foo');&lt;/code&gt; is the same as &lt;code&gt;var value = widget.foo;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;just remember that if you provide the custom function to set/get then you will need to update the object property directly if you need it updated.  &lt;code&gt;widget.attr('foo', value);&lt;/code&gt; won't update &lt;code&gt;widget.foo&lt;/code&gt; if you have &lt;code&gt;_setFooAttr&lt;/code&gt; defined as a function in your widget.  also, if you provide either of the custom functions, you are not required to provide the other one.  so, for example, you might provide the setter function but not the getter function.  in this case, the setter function will be used to set and the object property will be used for get.&lt;br /&gt;&lt;br /&gt;ok, so knowing this, we can keep this in mind when we're creating widgets and leverage it as needed.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;how dijit.form.Form uses setters and getters&lt;/h2&gt;&lt;br /&gt;now that we know about &lt;code&gt;.attr&lt;/code&gt; we can look into how it's used for setting/getting values for &lt;code&gt;dijit.form.Form&lt;/code&gt;.  the value for a form is generated from the elements contained in that form.  for &lt;code&gt;dijit.form.Form&lt;/code&gt; it looks for all the widgets that are the descendants of it's &lt;code&gt;containerNode&lt;/code&gt; and if that widget has a &lt;code&gt;name&lt;/code&gt; property then the form value will have a property name that matches the value of the name of the widget.  so, for example, if the widget's name is &lt;code&gt;foo&lt;/code&gt; then the form's value will contain a &lt;code&gt;foo&lt;/code&gt; property.  the value of this property is obtained by getting the widget's value via &lt;code&gt;widget.attr('value');&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;setting a &lt;code&gt;dijit.form.Form&lt;/code&gt; value is simply the reverse of this.  the form looks to the value being set and for the properties of that value, it looks for a child widget with a &lt;code&gt;name&lt;/code&gt; to match that property and then tries to set that widget's value via &lt;code&gt;widget.attr('value', formValue.widgetName);&lt;/code&gt; - this explanation does not follow the code exactly but the end result is the same.  you should read the code if you want exact details :)&lt;br /&gt;&lt;br /&gt;so, now that we know this, it's easy to see how if we have a &lt;code&gt;dijit.form.TextBox&lt;/code&gt; with the &lt;code&gt;name&lt;/code&gt; property set to &lt;code&gt;firstName&lt;/code&gt; inside a form then we would expect the following&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;    var form = dijit.byId('aForm');  // get a handle to the form&lt;br /&gt;&lt;br /&gt;    var value = form.attr('value');  // value.firstName will be the value of the dijit.form.TextBox&lt;br /&gt;&lt;br /&gt;    form.attr('value', {firstName: 'Bob'});  // the dijit.form.TextBox will now have the value 'Bob'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;well this is easy for forms where we have a fixed number of fields and our data is 'flat' - ie, each widget just returns a string, a number, a boolean or even a Date.  &lt;br /&gt;&lt;br /&gt;what do we do though if we want to do something a little more complex?  for example, we might have a form where a user can   enter their name (first, last) and their address (street, city, state, zip, country).  we could have a form where we have fields with names to match each of these but what if we wanted to treat the address as an object so that at the top-level, our form only has 3 properties (first, last, address)?  well, we would need to have 3 widgets that have these names - first, last, address.  ok, that's easy but &lt;code&gt;dijit&lt;/code&gt; doesn't have an address widget!  so... now it's time for us to write our own widget.&lt;br /&gt;&lt;br /&gt;based on what we know about &lt;code&gt;.attr&lt;/code&gt; and &lt;code&gt;dijit.form.Form&lt;/code&gt; here's what our widget will have to do:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;widget.attr('value');&lt;/code&gt; will have to return an object that has properties called street, city, state, zip, country&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;widget.attr('value', formValue.address);&lt;/code&gt; will need to take an object with the above properties and display them appropriately&lt;/li&gt;&lt;br /&gt;&lt;li&gt;and our widget needs to have a &lt;code&gt;name&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;so, it looks like we will need to know how to build our own widgets to do this.  fortunately, if you know enough about dojo to have been able to build a form with fields for street, city, state, zip and country then you're just a step or 2 away from being able to break out those fields into a widget.&lt;br /&gt;&lt;br /&gt;well, every good tutorial has sample code, right?  and i'm going to follow that trend but my code relates to a slightly more complex problem.  once we work through the sample, then you should be able to come back and write the code for the problem described above.&lt;br /&gt;&lt;br /&gt;the sample code will build a form that will allow a user to enter a schedule.  so, they can choose the date for their schedule and then add tasks/events for that date.  each of these tasks, will have a time and a description.  the extra level of complexity that we have from the first problem (described above) is that we are going to allow the user to add or remove tasks which will mean we have a dynamic number of fields in our form.  keep in mind, this problem was contrived just to demonstrate the principles in the code - it will be lacking in many ways but it serves the purpose of demonstrating the principles i'm trying to explain.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;our high level design&lt;/h2&gt;&lt;br /&gt;basically, our design is driven by our data format.  at the top-level, our data has 2 properties:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;date&lt;/code&gt; - the date of our schedule&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;tasks&lt;/code&gt; - the list of tasks we have scheduled for this day&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;our list of tasks will be an array of objects.  each of these objects will have the following properties:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;time&lt;/code&gt; - the time the task begins&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;description&lt;/code&gt; - a description of the task&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;from this, we see that we need a widget for selecting a date (we'll choose dijit._Calendar) and we need a widget that can manage the list of tasks.  since we can add and remove tasks from this list, then it seems like it would also be convenient to build a widget to represent a single task.  this task widget will then need a widget for selecting a time (dijit.form.TimeTextBox) and another widget to enter a description (dijit.form.TextBox).  &lt;br /&gt;&lt;br /&gt;ok, so now that we have a high level design, we can start getting into the details of building these widgets.  let's start with the widget for a single task and then work our way back up to the top-level of the form.  &lt;a href="http://neonstalwart.dojotoolkit.org/blog/20091121/"&gt;you can look at the finished example&lt;/a&gt; if you want to see what we're working towards.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;my.widgets.Task&lt;/h2&gt;&lt;br /&gt;&lt;blockquote&gt;this task widget will then need a widget for selecting a time (dijit.form.TimeTextBox) and another widget to enter a description (dijit.form.TextBox).&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;to keep this simple, we're going to leverage dijit's templating class - &lt;code&gt;dijit._Templated&lt;/code&gt;.  this allows us to define the high level DOM structure of our widget using html.  based on our design, we can see that this should be fairly simple.  the template for our Task widget is simply:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;&amp;lt;div class='task'&gt;&lt;br /&gt; &amp;lt;div dojoType='dijit.form.TimeTextBox' dojoAttachPoint='timeInput'&gt;&amp;lt;/div&gt;&lt;br /&gt; &amp;lt;div dojoType='dijit.form.TextBox' dojoAttachPoint='descInput'&gt;&amp;lt;/div&gt;&lt;br /&gt;&amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;this is really simple.  we have the outer div which becomes the &lt;code&gt;domNode&lt;/code&gt; of our widget.  we have put a class on this node so that we can easily style any part of this widget by including that class in our selector if necessary.  this outer node has 2 children - 1 for our time widget and 1 for our description.  using &lt;code&gt;dojoType&lt;/code&gt; we can specify which widgets we want to have at the respective places in the DOM.  in our javascript file that defines our widget, we just need to remember to set the &lt;code&gt;widgetsInTemplate&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt; so that our template gets parsed and those nodes get turned into widgets.  we have also added &lt;code&gt;dojoAttachPoint&lt;/code&gt;s to our template.  this allows us to map those widgets (in our template) to properties of our Task widget.  by doing this, we can easily reference those individual widgets through those properties and one thing this will do is allow us to easily set or get the values of those widgets.  so far, so good!&lt;br /&gt;&lt;br /&gt;next we'll look at the javascript file which goes along with this template:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;dojo.provide('my.widgets.Task');&lt;br /&gt;&lt;br /&gt;dojo.require('dijit._Widget');&lt;br /&gt;dojo.require('dijit._Templated');&lt;br /&gt;dojo.require('dijit.form.TimeTextBox');&lt;br /&gt;dojo.require('dijit.form.TextBox');&lt;br /&gt;&lt;br /&gt;dojo.declare('my.widgets.Task', [dijit._Widget, dijit._Templated], {&lt;br /&gt; templatePath: dojo.moduleUrl('my.widgets.templates', 'Task.html'),&lt;br /&gt; widgetsInTemplate: true,&lt;br /&gt; &lt;br /&gt; _setValueAttr: function(value){&lt;br /&gt;  if(value){&lt;br /&gt;   this.timeInput.attr('value', value.time || null);&lt;br /&gt;   this.descInput.attr('value', value.description || '');&lt;br /&gt;  } else {&lt;br /&gt;   this.timeInput.attr('value', null);&lt;br /&gt;   this.descInput.attr('value', '');&lt;br /&gt;  }&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; _getValueAttr: function(){&lt;br /&gt;  return {&lt;br /&gt;   time: this.timeInput.attr('value'),&lt;br /&gt;   description: this.descInput.attr('value')&lt;br /&gt;  };&lt;br /&gt; }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ok - that's a little more code than the last block so let's break it down.&lt;br /&gt;&lt;br /&gt;the first line is used by dojo's packaging system.  this line identifies that this file provides the code for the 'my.widget.Task' package.  the next few lines also relate to dojo's packaging system.  they are just specifying the dependencies of this 'class'.  the real meat of what we're looking at is inside &lt;code&gt;dojo.declare&lt;/code&gt;.  you can see that we are extending &lt;code&gt;dijit._Widget&lt;/code&gt; and &lt;code&gt;dijit._Templated&lt;/code&gt;.  if you need more details about what's happening here then i'll leave it up to you to find out about this.  the simple explanation here is that these are the 2 classes you most typically use to build a widget based on a template.&lt;br /&gt;&lt;br /&gt;the next 2 lines define the path to our template and also let the templating system know that we have widgets in our template so it needs to parse the template to generate those widgets.&lt;br /&gt;&lt;br /&gt;that leaves the 2 functions.  if you can remember all the way back to the start, you'll know that these 2 functions are the custom functions used as setter/getter.  &lt;br /&gt;&lt;br /&gt;the setter checks if a parameter is passed in and sets the values of the time (&lt;code&gt;this.timeInput&lt;/code&gt;) and description (&lt;code&gt;this.descInput&lt;/code&gt;) widgets based on the value passed in.  you can see how we're making use of the &lt;code&gt;dojoAttachPoint&lt;/code&gt;s that we indicated in our template and we're also using &lt;code&gt;.attr&lt;/code&gt; to set the value of those widgets.  this is the beauty of a standardized interface.&lt;br /&gt;&lt;br /&gt;the getter simply forms an object with property names we're expecting (time, description) and assigns values to the properties based on the &lt;code&gt;.attr&lt;/code&gt; getter for each of the widgets.&lt;br /&gt;&lt;br /&gt;now that we have our Task widget, we can use it to build a list of tasks.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;my.widgets.TaskList&lt;/h2&gt;&lt;br /&gt;ok, we're building on what we've learned already - no point in stopping here, we're going all the way :)  i'll try to keep you a little entertained amidst all this learning.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;...we need a widget that can manage the list of tasks.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;this widget will manage our list of tasks - it will provide ways to:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;add a task&lt;/li&gt;&lt;br /&gt;&lt;li&gt;remove a task&lt;/li&gt;&lt;br /&gt;&lt;li&gt;set the value from a list of tasks&lt;/li&gt;&lt;br /&gt;&lt;li&gt;return the list of tasks represented by this widget&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;add a task&lt;/h3&gt;&lt;br /&gt;we'll include a single button that will add another task with the current time and a default description of 'New Task'&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;remove a task&lt;/h3&gt;&lt;br /&gt;for each task that we add, we'll add a button which will provide a way for the user to remove that task&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;set the value from a list of tasks &amp; return the list of tasks represented by this widget&lt;/h3&gt;&lt;br /&gt;for this, we'll write a custom setter and a custom getter - &lt;code&gt;_setValueAttr&lt;/code&gt; and &lt;code&gt;_getValueAttr&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;dijit._Container&lt;/h3&gt;&lt;br /&gt;since this widget will be a container for other widgets, we will mixin &lt;code&gt;dijit._Container&lt;/code&gt; which will provide us with some functions to help managing adding/removing other widgets under our control.  the only thing we really need to consider for this is that we need to designate a node as our &lt;code&gt;containerNode&lt;/code&gt; so that these helpful functions will work :)&lt;br /&gt;&lt;br /&gt;with all of this in mind, here's the template for this widget:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;&amp;lt;div class='taskList'&gt;&lt;br /&gt; &amp;lt;div dojoAttachPoint='containerNode'&gt;&amp;lt;/div&gt;&lt;br /&gt; &amp;lt;div class='add'&gt;&lt;br /&gt;  &amp;lt;div dojoType='dijit.form.Button' dojoAttachEvent='onClick:newTask' iconClass='plusIcon'&gt;Add Task&amp;lt;/div&gt;&lt;br /&gt; &amp;lt;/div&gt;&lt;br /&gt;&amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;you can see, we've got some similarities to the previous template but we also have some new features we didn't see before.  i'm going to concentrate on the differences.  you can see that we defined the &lt;code&gt;containerNode&lt;/code&gt; we needed for &lt;code&gt;dijit._Container&lt;/code&gt; using &lt;code&gt;dojoAttachPoint&lt;/code&gt;.  this is where our Task widgets will be added to when we add them.&lt;br /&gt;&lt;br /&gt;the main feature we've used here that we didn't use previously is &lt;code&gt;dojoAttachEvent&lt;/code&gt;.  this provides a convenient way for us to connect the function of a widget in our template to a function defined in our TaskList class.  the way it works, is that the string before the ':' is the name of the button's function that will be connected to our widgets function - the name on the right of the ':'.  the connection is made by using the widget's &lt;code&gt;connect&lt;/code&gt; method and this is just a convenient way to shortcut the code to do that.  you can see from our template that when the &lt;code&gt;onClick&lt;/code&gt; of the button is called, we will execute the &lt;code&gt;newTask&lt;/code&gt; function of our widget.&lt;br /&gt;&lt;br /&gt;now let's look at the javascript code so we can see what it looks like&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;dojo.provide('my.widgets.TaskList');&lt;br /&gt;&lt;br /&gt;dojo.require('dijit._Widget');&lt;br /&gt;dojo.require('dijit._Container');&lt;br /&gt;dojo.require('dijit._Templated');&lt;br /&gt;dojo.require('dijit.form.Button');&lt;br /&gt;dojo.require('my.widgets.Task');&lt;br /&gt;&lt;br /&gt;dojo.declare('my.widgets.TaskList', [dijit._Widget, dijit._Templated, dijit._Container], {&lt;br /&gt; templatePath: dojo.moduleUrl('my.widgets.templates', 'TaskList.html'),&lt;br /&gt; widgetsInTemplate: true,&lt;br /&gt; &lt;br /&gt; name:'',&lt;br /&gt; _multiValue: true,&lt;br /&gt; &lt;br /&gt; postCreate: function(){&lt;br /&gt;  if(!this.getChildren().length){&lt;br /&gt;   // add a default 'blank' task&lt;br /&gt;   this.newTask();&lt;br /&gt;  }&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // this creates a 'blank' new task - defaults the time to now and the description is 'New Task'&lt;br /&gt; newTask: function(){&lt;br /&gt;  this.addTask({&lt;br /&gt;   time: new Date(),&lt;br /&gt;   description: 'New Task'&lt;br /&gt;  });&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // adds a single task to our list of tasks&lt;br /&gt; addTask: function(task){&lt;br /&gt;  new my.widgets.Task({&lt;br /&gt;   value: task&lt;br /&gt;  }).placeAt(this);&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // sets our value - takes an array of objects&lt;br /&gt; // each object should have a time and a description property&lt;br /&gt; _setValueAttr: function(value){&lt;br /&gt;  // if we already have a value then we need to clear the widgets that represent that value&lt;br /&gt;  // removes all the widgets inside our 'containerNode'&lt;br /&gt;  this.destroyDescendants();&lt;br /&gt;  if(dojo.isArray(value) &amp;&amp; value.length){&lt;br /&gt;   dojo.forEach(value, this.addTask, this);&lt;br /&gt;  } else {&lt;br /&gt;   // default to a 'blank' task&lt;br /&gt;   this.newTask();&lt;br /&gt;  }&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; _getValueAttr: function(){&lt;br /&gt;  // this will return an array of the values returned from our children via child.attr('value')&lt;br /&gt;  return dojo.map(this.getChildren(), "return item.attr('value');");&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; addChild: function(child){&lt;br /&gt;  this.inherited(arguments);&lt;br /&gt;  var button = new dijit.form.Button({&lt;br /&gt;   label: 'Remove Task',&lt;br /&gt;   showLabel: false,&lt;br /&gt;   iconClass: 'dijitEditorIcon dijitEditorIconCancel',&lt;br /&gt;   onClick: dojo.hitch(this, function(){&lt;br /&gt;    this.removeChild(child);&lt;br /&gt;    button.destroy();&lt;br /&gt;   })&lt;br /&gt;  }).placeAt(child.domNode);&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; removeChild: function(){&lt;br /&gt;  this.inherited(arguments);&lt;br /&gt;  if(!this.getChildren().length){&lt;br /&gt;   this.newTask();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;these blocks of code are getting bigger and bigger but that's ok.  we've only added a few new concepts.  most of it is familiar already.  let's jump right past what's already familiar and take a look at the new properties we're adding to this widget (name, _multiValue).  the &lt;code&gt;name&lt;/code&gt; property needs to be defined so that it can be picked up by the parser when we add this widget to our form.  properties defined in markup will only be added by the parser to the widget if the properties are in the prototype of the widget.  so we have to define &lt;code&gt;name&lt;/code&gt; so we can use it later.  also, &lt;code&gt;_multiValue&lt;/code&gt; is a property we need to set as &lt;code&gt;true&lt;/code&gt; whenever we will be setting/getting an array as the value of this widget.&lt;br /&gt;&lt;br /&gt;i'm just going to summarize quickly what each of the functions do:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;postCreate&lt;/h3&gt;&lt;br /&gt;just adds an empty task if no value was passed in when the widget was created&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;newTask&lt;/h3&gt;&lt;br /&gt;this is the function called when the user clicks the button to add a task.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;addTask&lt;/h3&gt;&lt;br /&gt;this function is used to add another task to our list.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;_setValueAttr&lt;/h3&gt;&lt;br /&gt;removes any previous tasks, adds each task in the list, or adds a 'blank' task if the new list is empty &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;_getValueAttr&lt;/h3&gt;&lt;br /&gt;returns an array which holds the results of calling the &lt;code&gt;.attr('value');&lt;/code&gt; getter for each child.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;addChild&lt;/h3&gt;&lt;br /&gt;we're extending this function to add a button to each of our children so that when the button is clicked, the child is removed and the button is also destroyed.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;removeChild&lt;/h3&gt;&lt;br /&gt;we're extending this function to add a 'blank' task to the list if we remove the last child.&lt;br /&gt;&lt;br /&gt;ok - take some time and digest that... we have 1 final piece and that's the form.  this is what we've been trying to achieve from the start... and it's taken quite a while to get here.  you can see why i didn't want to keep explaining this any more!&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;my.widgets.App&lt;/h2&gt;&lt;br /&gt;&lt;blockquote&gt;at the top-level, our data has 2 properties:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;date&lt;/code&gt; - the date of our schedule&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;tasks&lt;/code&gt; - the list of tasks we have scheduled for this day&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;it's a long way to the top if you want to rock n roll but we've finally made it!  well, you already know what we're trying to achieve so here's the code:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;&amp;lt;div class='myApp'&gt;&lt;br /&gt; &amp;lt;form dojoType='dijit.form.Form' dojoAttachPoint='form'&gt;&lt;br /&gt;  &amp;lt;h1&gt;Daily Schedule&amp;lt;/h1&gt;&lt;br /&gt;  &amp;lt;input dojoType='dijit._Calendar' dojoAttachEvent='onChange:onDateChange' name='date' class='dijitInline' /&gt;&lt;br /&gt;  &amp;lt;input dojoType='my.widgets.TaskList' name='tasks' class='dijitInline'/&gt;&lt;br /&gt; &amp;lt;/form&gt;&lt;br /&gt;&amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;this time, our template contains a form which contains a heading and 2 elements.  we really haven't introduced any new concepts here so since this post is already a mammoth i'll leave it for you to read it and comprehend it.&lt;br /&gt;&lt;br /&gt;and fortunately, most of the hard work has already been done so the javascript is just shown here to complete the code:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;&lt;br /&gt;dojo.provide('my.widgets.App');&lt;br /&gt;&lt;br /&gt;dojo.require('dijit.form.Form');&lt;br /&gt;dojo.require('dijit._Calendar');&lt;br /&gt;dojo.require('dijit.form.TextBox');&lt;br /&gt;dojo.require('my.widgets.TaskList');&lt;br /&gt;&lt;br /&gt;// a little hack to get dijit._Calendar to work with the parser.&lt;br /&gt;// dijit.form.Form only takes values from widgets with names and&lt;br /&gt;// the parser only sees properties in the markup which already&lt;br /&gt;// exist in the prototype - hence...&lt;br /&gt;dojo.extend(dijit._Calendar, {&lt;br /&gt; name: ''&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;dojo.declare('my.widgets.App', [dijit._Widget, dijit._Templated], {&lt;br /&gt; templatePath: dojo.moduleUrl('my.widgets.templates', 'App.html'),&lt;br /&gt; widgetsInTemplate: true,&lt;br /&gt; &lt;br /&gt; // this is just going to be something to connect to so we can know when the user selects a new date&lt;br /&gt; onDateChange: function(value){}&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;there's probably only 2 things which need explaining here.   the &lt;code&gt;dojo.extend&lt;/code&gt; and the empty &lt;code&gt;onDateChange&lt;/code&gt; function.&lt;br /&gt;&lt;br /&gt;the &lt;code&gt;dojo.extend&lt;/code&gt; is needed so that we can give the calendar a &lt;code&gt;name&lt;/code&gt; property in the template.  if you remember i said earlier:&lt;br /&gt;&lt;blockquote&gt;properties defined in markup will only be added by the parser to the widget if the properties are in the prototype of the widget.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;it turns out that &lt;code&gt;dijit._Calendar&lt;/code&gt; doesn't have the name property defined because it wasn't intended to be used like this (until dojo 1.4).&lt;br /&gt;&lt;br /&gt;and the &lt;code&gt;onDateChange&lt;/code&gt; function is here so that we can connect to this function and do something based on when the user selects a different date.  since this post is so long... that's another post for another day :)&lt;br /&gt;&lt;br /&gt;hopefully i've helped you get inside the 'brain of dojo' and now you can see some of the patterns that have been designed into dojo and you can leverage these patterns to work &lt;em&gt;with&lt;/em&gt; dojo rather than fight against it or re-invent the wheel.&lt;br /&gt;&lt;br /&gt;thanks for staying through to the end.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-629053179544942579?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/629053179544942579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=629053179544942579' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/629053179544942579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/629053179544942579'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2009/11/working-with-dijitformform.html' title='working &lt;em&gt;with&lt;/em&gt; dijit.form.Form'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-510631440168781866</id><published>2009-05-14T19:11:00.005-05:00</published><updated>2009-05-14T20:37:30.202-05:00</updated><title type='text'>fetching everything selected in dojox.grid.DataGrid</title><content type='html'>&lt;span style="font-weight:bold;"&gt;the problem&lt;/span&gt;&lt;br /&gt;the dojox.grid.DataGrid can page data and use virtual scrolling so that you can display a grid that can potentially display any of the data without needing to load all of it.  the problem that we face with this is that if a user selects a row at the top of your data, quickly scrolls down towards the end of the data, holds shift and selects another row, then all the rows in between will be selected.  this is fine - in fact this is desirable.  however, since not all the rows in between were displayed then some of the data may not have been loaded.  that is the problem.  when we call &lt;pre class="prettyprint" style="overflow:auto"&gt;grid.selection.getSelected()&lt;/pre&gt; then it will return an array of items that might have some null items - these were the items that were not yet fetched.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;the workaround&lt;/span&gt;&lt;br /&gt;is an asynchronous getSelected() that takes a callback as a parameter.  a warning should be given that this workaround is not thorough and maybe it should be called a &lt;span style="font-style:italic;"&gt;hack&lt;/span&gt;!  for me it's a proof of concept and would be a "nice to have" if dojo can provide something like this.  the steps involved are straight forward&lt;ul&gt;&lt;li&gt;get the selected items in a similar manner to how it already happens with getSelected()&lt;/li&gt;&lt;li&gt;while getting those results, build an array of rows that need to be loaded&lt;/li&gt;&lt;li&gt;walk the array of unloaded items and fetch the missing pages of data&lt;/li&gt;&lt;li&gt;as each page is fetched, push the items into the original results&lt;/li&gt;&lt;li&gt;when we have all the pages, call the callback with the complete result set&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;here's &lt;span style="font-weight:bold;"&gt;the code&lt;/span&gt; pulled from a modified version of dojox.grid.DataSelection:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;getSelectedAsync: function(cBack){&lt;br /&gt;    var result=[];&lt;br /&gt;    var load=[];&lt;br /&gt;    var requests=0;&lt;br /&gt;    for(var i=0, l=this.selected.length; i&amp;lt;l; i++){&lt;br /&gt;        if(this.selected[i]){&lt;br /&gt;            var item = this.grid.getItem(i);&lt;br /&gt;            item ? result.push(item) : load[i]=true;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    for(var j=0, m=load.length; j&amp;lt;m; j++){&lt;br /&gt;        if(load[j]){&lt;br /&gt;            var pageIndex = this.grid._rowToPage(j);&lt;br /&gt;&lt;br /&gt;            requests++;&lt;br /&gt;            var fetchDfd = dojo.connect(this.grid, "_onFetchComplete", function(items){&lt;br /&gt;                dojo.disconnect(fetchDfd);&lt;br /&gt;                // for some reason we get called too many times...&lt;br /&gt;                if(requests--){&lt;br /&gt;                    dojo.forEach(items, function(i){&lt;br /&gt;                        result.push(i);&lt;br /&gt;                    });&lt;br /&gt;                }&lt;br /&gt;                if(requests == 0){&lt;br /&gt;                    cBack(result);&lt;br /&gt;                }&lt;br /&gt;            });&lt;br /&gt;&lt;br /&gt;            // request the missing page&lt;br /&gt;            this.grid._requestPag(pageIndex);&lt;br /&gt;            // skip the other items in this page so we don't have extra requests&lt;br /&gt;            j = this.grid._pageToRow(pageIndex+1);  // -1 maybe? to account for j++ above&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;the warnings&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;this will defeat part of the purpose of the grid.  the grid tries to only load pages on an "as needed" basis so that you don't have to load all of the data at one time.  this goes against that idea.&lt;/li&gt;&lt;li&gt;for some reason i'm getting extra callbacks from the connect to "_onFetchComplete" and until i take the time to track them down, i would suggest that you use this at your own risk ;)&lt;/li&gt;&lt;li&gt;i've used a number of "private" functions to achieve this.  that's both good and (potentially) bad.  private functions are not promised to be unchanged from one release to the next but using them means that i don't have to repeat a lot of the work that is being done in these functions&lt;/li&gt;&lt;/ul&gt;i would certainly like to hear any comments about improvements to this and given a little time to live with it, i may at least search out the possibility of having something like this added to dojox.grid.DataSelection since after all DataSelection is for use with stores that implement the dojo.data api and many of them are largely asynchronous by nature.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-510631440168781866?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/510631440168781866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=510631440168781866' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/510631440168781866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/510631440168781866'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2009/05/fetching-everything-selected-in.html' title='fetching everything selected in dojox.grid.DataGrid'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-6490502435087326619</id><published>2009-02-07T00:10:00.002-06:00</published><updated>2009-02-07T00:12:16.823-06:00</updated><title type='text'>inspiration</title><content type='html'>if you're involved in open source at all and haven't seen this, you should - especially if you're just hanging around the edges and not comfortable with diving right in.  this was a great inspiration to me to get involved.&lt;br /&gt;&lt;br /&gt;&lt;embed src="http://yapc.tv/swf/player.swf" quality="high" bgcolor="#FFFFFF" width="720" height="596" allowfullscreen="true" allowscriptaccess="always" flashvars="file=http://yapc.tv/hi/2008/ye/lt/lt1-12-trout-arent-good-enough.flv&amp;image=http://yapc.tv/2008/ye/lt/lt1-12-trout-arent-good-enough/preview.jpg&amp;fullscreen=true" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-6490502435087326619?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/6490502435087326619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=6490502435087326619' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/6490502435087326619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/6490502435087326619'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2009/02/blog-post.html' title='inspiration'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-2898460148288221860</id><published>2009-02-01T21:59:00.019-06:00</published><updated>2009-02-04T19:39:04.888-06:00</updated><title type='text'>dereferencing object properties in dojox.grid.DataGrid</title><content type='html'>i'm working on a demo for &lt;a href="http://persvr.org"&gt;Persevere&lt;/a&gt; and the interface is basically editable tables that represent the data that is persisted by Persevere.  the editable tables are the dojox.grid.DataGrid and the demo is a primitive calendar application.&lt;br /&gt;&lt;br /&gt;Persevere supports lazy loading and so if you have an Event object that has a calendar property to indicate which Calendar the event belongs in, that calendar is stored as a reference in the event.  similarly, if the calendar has an owner that is a User object, then the owner property will reference a User.  these objects that are stored as references have to be loaded before they can be referenced.&lt;br /&gt;&lt;br /&gt;in my grid that displays the list of events, i want my columns to show:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Calendar - the name of the calendar that the event belongs to&lt;/li&gt;&lt;li&gt;Date - the date of the event&lt;/li&gt;&lt;li&gt;Event Name - the name/title of the event&lt;/li&gt;&lt;li&gt;Description - some extra details about the event&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;the way i have my Event class, this would mean that the ideal layout for my grid would be something like this:&lt;br /&gt;&lt;pre class="prettyprint" style="overflow:auto"&gt;var layout = [&lt;br /&gt;    {width: "20%", name: "Calendar", field: "calendar.name"},&lt;br /&gt;    {width: "15%", editable: true, field: "date", name: "Date", type: dojox.grid.cells.DateTextBox},&lt;br /&gt;    {width: "30%", editable: true, field: "name", name: "Event Name"},&lt;br /&gt;    {width: "35%", editable: true, field: "description", name: "Description"}&lt;br /&gt;];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;unfortunately, the grid (or the store - depending on where you want to post the blame) doesn't support drilling down into the item by using "calendar.name" and so the first iteration of our solution is to use a custom get function.&lt;br /&gt;&lt;pre class="prettyprint"&gt;var getCalendar = function(row, item){&lt;br /&gt;   if(!item){&lt;br /&gt;        return this.defaultValue;&lt;br /&gt;    }&lt;br /&gt;    var store = this.grid.store;&lt;br /&gt;    var isItem = store &amp;&amp; store.isItem(item, true);&lt;br /&gt;    if(isItem){&lt;br /&gt;        var calendar = store.getValue(item, "calendar");&lt;br /&gt;        var name = store.getValue(calendar, "name");&lt;br /&gt;       return name;&lt;br /&gt;    }&lt;br /&gt;    return this.defaultValue;&lt;br /&gt;}&lt;br /&gt;var layout = [&lt;br /&gt;    {width: "20%", name: "Calendar", get: getCalendar},&lt;br /&gt;    {width: "15%", editable: true, field: "date", name: "Date", type: dojox.grid.cells.DateTextBox},&lt;br /&gt;    {width: "30%", editable: true, field: "name", name: "Event Name"},&lt;br /&gt;    {width: "35%", editable: true, field: "description", name: "Description"}&lt;br /&gt;];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;this is fine for this one column but what about if this grid had more columns that i wanted to do this to and then what if i had more grids with more columns like this... that's a lot of repeating and we don't like repeating.  so, the final iteration of our solution would ultimately be a subclass of dojox.grid.DataGrid that would allow us to use field names like "calendar.name"&lt;br /&gt;&lt;br /&gt;i haven't taken this all the way through to a subclass yet but i &lt;span style="font-style:italic;"&gt;have&lt;/span&gt; gone as far as overriding the default get method in the grid for each instance that i use this in.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WARNING:&lt;/span&gt; what i'm about to show here is only valid for reading and extra work probably needs to be done if you want to be able to edit these fields and have them write back to the store properly.  if i have the need for it then i'll work on the code for writing back to the store and at that point i feel it would be worth a complete subclass and possibly a request to a dojo committer to include this as part of the grid.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;var layout = [&lt;br /&gt;    {width: "20%", name: "Calendar", field: "calendar.name"},&lt;br /&gt;    {width: "15%", editable: true, field: "date", name: "Date", type: dojox.grid.cells.DateTextBox},&lt;br /&gt;    {width: "30%", editable: true, field: "name", name: "Event Name"},&lt;br /&gt;    {width: "35%", editable: true, field: "description", name: "Description"}&lt;br /&gt;];&lt;br /&gt;var grid = new dojox.grid.DataGrid({&lt;br /&gt;    structure: layout,&lt;br /&gt;    region: 'center',&lt;br /&gt;    store: this.store,&lt;br /&gt;    get: function(rowIndex, inItem){&lt;br /&gt;        var grid = this.grid;&lt;br /&gt;        var dereference = function(item, field){&lt;br /&gt;            var props = field.concat().split('.');&lt;br /&gt;            var val = item;&lt;br /&gt;            dojo.forEach(props, function(prop){&lt;br /&gt;                val = grid.store.getValue(val, prop);&lt;br /&gt;            });&lt;br /&gt;            return val;&lt;br /&gt;        }&lt;br /&gt;  return (!inItem ? this.defaultValue : (!this.field ? this.value : dereference(inItem, this.field)));&lt;br /&gt;    }&lt;br /&gt;}, dojo.doc.createElement('div')).placeAt(this);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;this code is taken from a custom widget that is a subclass of dijit.layout.BorderContainer that i'm using so take that into consideration when looking at lines like the last line of code that places the grid at this.&lt;br /&gt;&lt;br /&gt;something worth noting is that inside the get function, the context is a cell.&lt;br /&gt;&lt;br /&gt;to conclude, i'm certainly looking for any improvements to this and help with writing back to the store properly would be appreciated too.  ultimately, i would like this functionality to be included in the grid.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-2898460148288221860?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/2898460148288221860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=2898460148288221860' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2898460148288221860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2898460148288221860'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2009/02/dereferencing-object-properties-in.html' title='dereferencing object properties in dojox.grid.DataGrid'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-7549573929442124994</id><published>2009-01-15T14:55:00.003-06:00</published><updated>2009-01-15T15:30:52.659-06:00</updated><title type='text'>dojo.data.ItemFileWriteStore</title><content type='html'>when starting to use the dojo data API, the first store that most people learn to use is the dojo.data.ItemFileReadStore (read only) and it's counterpart dojo.data.ItemFileWriteStore (read &amp; write).  out of the box, dojo.data.ItemFileWriteStore (IFWS) doesn't actually have a mechanism to write anything anywhere.  everything is in place to write, but the functions that actually do the writing are essentially a no-op and so you have to write your own.  this is something that is not clearly obvious when you start to use IFWS and so it needs to be clearly stated.  also, here is a simple example of writing to your server URL.  NOTE: IFWS is not a very efficient store since ALL the data is written each time the store is saved.&lt;br /&gt;&lt;br /&gt;the complete example is available &lt;a href="http://djtest.neonstalwart.site90.net/samfuqua.html"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;here's the javascript:&lt;br /&gt;&lt;pre name="code" class="javascript:nogutter"&gt;&lt;br /&gt;            dojo.require("dojox.grid.DataGrid");&lt;br /&gt;            dojo.require("dojo.data.ItemFileWriteStore");&lt;br /&gt;            dojo.require("dijit.form.Button");&lt;br /&gt;            &lt;br /&gt;            var fillStore = function(){&lt;br /&gt;             dojo.xhrGet({&lt;br /&gt;                 url: "samfuqua.json",&lt;br /&gt;                 handleAs: "json",&lt;br /&gt;                 load: function(data, ioArgs){&lt;br /&gt;                     dijit.byId('table').setStore(new dojo.data.ItemFileWriteStore({&lt;br /&gt;                         data: data&lt;br /&gt;                     }));&lt;br /&gt;                     dijit.byId('table').store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){&lt;br /&gt;                        console.log(newFileContentString);&lt;br /&gt;                        dojo.xhrPost({&lt;br /&gt;                             url: "yourURL",&lt;br /&gt;                             postData: dojo.toJson(dojo.fromJson(newFileContentString)), // this unprettifies the string&lt;br /&gt;                             error: saveFailedCallback,&lt;br /&gt;                             load: saveCompleteCallback&lt;br /&gt;                         });&lt;br /&gt;                     }&lt;br /&gt;                 }&lt;br /&gt;             });&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            dojo.addOnLoad(fillStore);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and here's the html:&lt;br /&gt;&lt;pre name="code" class="html:nogutter"&gt;&lt;br /&gt; &amp;lt;body class="tundra"&gt;&lt;br /&gt;     &amp;lt;button dojoType="dijit.form.Button" onclick="dijit.byId('table').store.revert();"&gt;Revert&amp;lt;/button&gt;&lt;br /&gt;     &amp;lt;button dojoType="dijit.form.Button" onclick="dijit.byId('table').store.save();"&gt;Save&amp;lt;/button&gt;&lt;br /&gt;        &amp;lt;table id="table" dojoType="dojox.grid.DataGrid"&gt;&lt;br /&gt;            &amp;lt;thead&gt;&lt;br /&gt;                &amp;lt;tr&gt;&lt;br /&gt;                    &amp;lt;th field="genre"&gt;Genre&amp;lt;/th&gt;&lt;br /&gt;                    &amp;lt;th field="author" editable=true&gt;Author&amp;lt;/th&gt;&lt;br /&gt;                    &amp;lt;th field="title"&gt;Title&amp;lt;/th&gt;&lt;br /&gt;                    &amp;lt;th field="price"&gt;Price&amp;lt;/th&gt;&lt;br /&gt;                &amp;lt;/tr&gt;&lt;br /&gt;            &amp;lt;/thead&gt;&lt;br /&gt;        &amp;lt;/table&gt;&lt;br /&gt; &amp;lt;/body&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;the part to focus in on is this section here:&lt;br /&gt;&lt;pre name="code" class="javascript:nogutter"&gt;&lt;br /&gt;                     dijit.byId('table').store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){&lt;br /&gt;                        console.log(newFileContentString);&lt;br /&gt;                        dojo.xhrPost({&lt;br /&gt;                             url: "yourURL",&lt;br /&gt;                             postData: dojo.toJson(dojo.fromJson(newFileContentString)), // this unprettifies the string&lt;br /&gt;                             error: saveFailedCallback,&lt;br /&gt;                             load: saveCompleteCallback&lt;br /&gt;                         });&lt;br /&gt;                     }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;for IFWS to actually do something, you have to override either the _saveEverything or the _saveCustom functions.  in this case, we are overriding _saveEverything.  when IFWS calls the _saveEverything function it will pass a saveCompleteCallback, saveFailedCallback and a newFileContentString.  conveniently, these are basically what we would need to have to make an xhrPost to our server :)&lt;br /&gt;&lt;br /&gt;the xhrPost is fairly straightforward, you provide a url, some data, an error callback and a load (success) callback.  the only manipulation we've had to do here is "unprettify" the newFileContentString.  when newFileContentString is passed in, it is a "prettified" json string - ie it has tabs, and newlines, etc. to format the string so that it looks "pretty" when it's printed.  this is nice if you're writing the text directly to a file but this can cause problems if your server needs to understand the data so to unprettify it, i've converted the json to an object and then back to json again without prettifying it.&lt;br /&gt;&lt;br /&gt;this is just a quick look at IFWS and for a more complete look at it, take a look at &lt;a href="http://docs.dojocampus.org/dojo/data/ItemFileWriteStore"&gt;the docs at dojocampus&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-7549573929442124994?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/7549573929442124994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=7549573929442124994' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/7549573929442124994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/7549573929442124994'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2009/01/dojodataitemfilewritestore.html' title='dojo.data.ItemFileWriteStore'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-2307428930933880529</id><published>2008-11-12T11:46:00.013-06:00</published><updated>2008-11-12T14:50:57.923-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dojo'/><title type='text'>multiple versions of dojo</title><content type='html'>so, you've inherited a project and it uses an old version of dojo and you really don't have the time to get up to speed with the changes that have happened in dojo since that release and your project &lt;em&gt;ain't broke&lt;/em&gt; so you don't really want to &lt;em&gt;fix&lt;/em&gt; it but somebody wants a new feature or noticed a small defect and even if this scenario doesn't completely match your circumstances... for some reason you have a need to be running 2 versions of dojo at the same time.  if this is the case then keep reading...&lt;br /&gt;&lt;br /&gt;first of all, for the attention impaired, here's a link to what we're working towards &lt;a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojo/tests/_base/_loader/scope/scope04.html"&gt;http://archive.dojotoolkit.org/nightly/dojotoolkit/dojo/tests/_base/_loader/scope/scope04.html&lt;/a&gt;.  this page shows dojo 0.4.3 from the aol cdn working beside the latest nightly build of dojo.&lt;br /&gt;&lt;br /&gt;i recently helped someone who had a project that used dojo 0.4.3 and according to them, on FF3 the initial dialog markup was being displayed as the page was loading even though there was inline styling that was supposed to keep them hidden.  i never confirmed this for myself but that is what they were telling me.  in this case, they didn't want to migrate their whole project but they just wanted to fix their dialogs.  so, it seemed that the path of least resistance was to run 2 versions of dojo side-by-side and leave most of the code alone and just migrate the dialogs.&lt;br /&gt;&lt;br /&gt;the book of dojo already has a section about &lt;a href="http://dojotoolkit.org/book/book-dojo/part-3-javascript-programming-dojo-and-dijit/multiple-versions-dojo-page"&gt;multiple versions of dojo in a page&lt;/a&gt; but it doesn't hurt to have another perspective on it.  so let's dig into &lt;a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojo/tests/_base/_loader/scope/scope04.html"&gt;this&lt;/a&gt;.  the basic idea is leave the old stuff alone and bring in the new stuff in a way that the old stuff is unaware of.&lt;br /&gt;&lt;br /&gt;i'll start at the top of the file and work down explaining each part - css, javascript and html.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;css&lt;/span&gt;&lt;br /&gt;this file links to 3 different style sheets and the first one and the third one are related to the nightly build version of dojo and the 2nd one is specifically related to the dijit tests.&lt;br /&gt;&lt;pre name="code" class="css:nogutter"&gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css"&gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="../../../../../dijit/tests/css/dijitTests.css"&gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;for the guy i was helping, he didn't want any changes to the styling he already had so the only css he had to add was:&lt;br /&gt;&lt;pre name="code" class="css:nogutter"&gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="dojoroot/dijit/themes/dijit.css"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;this file has the essential styles for the dialog (and other widgets) to function properly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt;&lt;br /&gt;since the ability to use multiple versions of dojo was only introduced in 1.1, if we are using a version that is pre 1.1 then we want to load the old version of dojo first.  in theory, if both versions you want to use are 1.1 or later then it may be possible to load either version first.  the important thing is the one which is loaded without using custom namespaces will be the one that gets the "dojo" namespace (and "dijit" and "dojox" if that version used them).  i would recommend that if both versions are 1.1 or later then it would be a good practice to give each one it's own custom namespace so that there is no confusion about which version of dojo you are referring to.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;loading the old version of dojo&lt;/span&gt;&lt;br /&gt;you shouldn't need to change anything here if you're working with a pre-existing project.  if you don't have djConfig defined then there should be no need to define it at this point.&lt;br /&gt;&lt;pre name="code" class="javascript:nogutter"&gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&gt;&lt;br /&gt;    //djConfig for 0.4.3 setup.&lt;br /&gt;    djConfig = {&lt;br /&gt;        isDebug: true&lt;br /&gt;    };&lt;br /&gt;&amp;lt;/script&gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;loading the new version of dojo&lt;/span&gt;&lt;br /&gt;now that the old version has used djConfig and loaded itself, it will be safe for us to make changes to djConfig and load in our 2nd version of dojo - making sure to use a custom namespace for this version.  the custom namespace is achieved through djConfig.scopeMap.  this tells dojo how to map it's namespaces.  in the example below "dojo" maps to "dojo10", "dijit" maps to "dijit10" and "dojox" maps to "dojox10".  it is worthwhile noting that djConfig.baseUrl should point to the directory containing the dojo.js file - this is not quite obvious from this example.&lt;br /&gt;&lt;pre name="code" class="javascript:nogutter"&gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&gt;&lt;br /&gt; //Need scope map defined in a script block. It will not work as part of the&lt;br /&gt; //djConfig attribute on the script that loads Dojo.&lt;br /&gt; //Also, just adding properties instead of redefining djConfig, since that&lt;br /&gt; //will wipe out djConfig values set up by the 0.4.3 dojo.&lt;br /&gt; djConfig.parseOnLoad = true;&lt;br /&gt; djConfig.baseUrl = "../../../../";&lt;br /&gt; djConfig.scopeMap = [&lt;br /&gt;  ["dojo", "dojo10"],&lt;br /&gt;  ["dijit", "dijit10"],&lt;br /&gt;  ["dojox", "dojox10"]     &lt;br /&gt; ];&lt;br /&gt;&amp;lt;/script&gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="../../../../dojo.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;putting this to use&lt;/span&gt;&lt;br /&gt;after getting the groundwork laid, now we can do something with this.  to use the old version, we just keep doing things like they were being done before.  calling dojo.require or using a dojoType tag or calling dojo.byId or dojo.addOnLoad will all use the 0.4.3 version of dojo since the 0.4.3 version took the "dojo" namespace.  to use the new version, we call dojo10.require or use dojo10Type tags, etc.  this is because we mapped the newer version of dojo to use the "dojo10", "dijit10" and "dojox10" namespaces.  refer to the book of dojo for &lt;a href="http://dojotoolkit.org/book/book-dojo/part-3-javascript-programming-dojo-and-dijit/multiple-versions-dojo-page#multiversionLimitations"&gt;limitations to this feature&lt;/a&gt;.&lt;br /&gt;&lt;pre name="code" class="javascript:nogutter"&gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&gt;&lt;br /&gt; dojo.require("dojo.widget.DropdownDatePicker");&lt;br /&gt; dojo10.require("dijit._Calendar");&lt;br /&gt; dojo10.require("dojo.date.locale");&lt;br /&gt; dojo10.require("dojo.parser"); // scan page for widgets&lt;br /&gt;&lt;br /&gt; dojo.addOnLoad(function(){&lt;br /&gt;  dojo.byId("output043").innerHTML = dojo.version.toString();&lt;br /&gt; });&lt;br /&gt; dojo10.addOnLoad(function(){&lt;br /&gt;  dojo.byId("output10").innerHTML = dojo10.version.toString();&lt;br /&gt; });&lt;br /&gt;&lt;br /&gt; function myHandler(id,newValue){&lt;br /&gt;  console.debug("onChange for id = " + id + ", value: " + newValue);&lt;br /&gt; }&lt;br /&gt;   &lt;br /&gt; function foobar(){&lt;br /&gt;  dojo.byId("typeOut").innerHTML = (typeof dojo.addClass);&lt;br /&gt; }&lt;br /&gt; setTimeout(foobar, 2000);&lt;br /&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;html&lt;/span&gt;&lt;br /&gt;finally, we get to the html.  the most important thing to notice here is the tags - "dojoType" vs "dojo10Type".  you will also notice that class="tundra" was put on the parent of the dijit._Calendar so that the tundra theme would be applied to that widget.&lt;br /&gt;&lt;pre name="code" class="html:nogutter"&gt;&lt;br /&gt;&amp;lt;h1&gt;Multiversion Dojo: 0.4.3 and 1.0&amp;lt;/h1&gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;p&gt;&amp;lt;b&gt;NOTE: This test only works with a built version of Dojo&amp;lt;/b&gt;&amp;lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p&gt;This page loads Dojo 0.4.3 and Dojo 1.0.&amp;lt;/p&gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;p&gt;Dojo 0.4.3 version: &amp;lt;span id="output043"&gt;&amp;lt;/span&gt;&amp;lt;/p&gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;p&gt;Dojo 1.0 version: &amp;lt;span id="output10"&gt;&amp;lt;/span&gt;&amp;lt;/p&gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;p&gt;&amp;lt;b&gt;dojo.addClass should be undefined:&amp;lt;/b&gt; &amp;lt;span id="typeOut"&gt;&amp;lt;/span&gt;&amp;lt;/p&gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;p&gt;&lt;br /&gt; &amp;lt;input dojoType="dropdowndatepicker" value="2006-10-31" &lt;br /&gt;            containerToggle="wipe" containerToggleDuration="300" &gt;&lt;br /&gt;&amp;lt;/p&gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;p class="tundra"&gt;&lt;br /&gt; &amp;lt;input id="calendar1" dojo10Type="dijit._Calendar" onChange="myHandler(this.id,arguments[0])"&gt;&lt;br /&gt;&amp;lt;/p&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;this was a problem i helped someone solve recently and thought it was worth blogging.  feel free to leave comments - good or bad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-2307428930933880529?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/2307428930933880529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=2307428930933880529' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2307428930933880529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2307428930933880529'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2008/11/multiple-versions-of-dojo.html' title='multiple versions of dojo'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-2185909736617222635</id><published>2008-10-16T17:41:00.041-05:00</published><updated>2008-10-16T19:05:14.780-05:00</updated><title type='text'>alternative syntax highlighting</title><content type='html'>an alternative way to do syntax highlighting is using the dojo toolkit.  dojo toolkit is a javascript library.&lt;br /&gt;&lt;br /&gt;add this code to your template in the same place described in the previous post.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;link href='http://o.aolcdn.com/dojo/1.2/dojox/highlight/resources/highlight.css' rel='stylesheet'/&gt;&lt;br /&gt;&amp;lt;link href='http://o.aolcdn.com/dojo/1.2/dojox/highlight/resources/pygments/default.css' rel='stylesheet'/&gt;&lt;br /&gt;&amp;lt;script djConfig='parseOnLoad: true' src='http://o.aolcdn.com/dojo/1.2/dojo/dojo.xd.js'/&gt;&lt;br /&gt;&amp;lt;script&gt;&lt;br /&gt;    dojo.require(&amp;quot;dojox.highlight&amp;quot;);&lt;br /&gt;    dojo.require(&amp;quot;dojox.highlight.languages._all&amp;quot;);&lt;br /&gt;    dojo.require(&amp;quot;dojox.highlight.languages.pygments._www&amp;quot;);&lt;br /&gt;    dojo.addOnLoad(function() {&lt;br /&gt;        dojo.query(&amp;quot;code&amp;quot;).forEach(dojox.highlight.init);&lt;br /&gt;    });&lt;br /&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;put all your code inside &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; blocks and use a &lt;code&gt;&amp;lt;code class="&lt;i&gt;lang&lt;/i&gt;"&amp;gt;&lt;/code&gt; to define the language for the code block.  valid values for &lt;i&gt;lang&lt;/i&gt; are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;cpp&lt;/li&gt;&lt;li&gt;css&lt;/li&gt;&lt;li&gt;delphi&lt;/li&gt;&lt;li&gt;django&lt;/li&gt;&lt;li&gt;html&lt;/li&gt;&lt;li&gt;javascript&lt;/li&gt;&lt;li&gt;python&lt;/li&gt;&lt;li&gt;sql&lt;/li&gt;&lt;li&gt;xml&lt;/li&gt;&lt;/ul&gt;unfortunately, since php is not supported, i probably won't end up using this option.  also, feel free to suggest any other options that i might like better than the 2 i've found so far.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-2185909736617222635?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/2185909736617222635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=2185909736617222635' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2185909736617222635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2185909736617222635'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2008/10/alternative-syntax-highlighting.html' title='alternative syntax highlighting'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3810921673000177425.post-2118567455323969287</id><published>2008-10-09T23:21:00.006-05:00</published><updated>2008-10-15T00:07:20.424-05:00</updated><title type='text'>first post - syntax highlighting</title><content type='html'>there are probably hundreds of posts about this already but here's another one for your pleasure...&lt;br /&gt;&lt;br /&gt;to get syntax highlighting in your blogger, click on the 'copy to clipboard' link below and then go to Layout-&gt;Edit HTML and paste the code right before the &amp;lt/body&amp;gt tag at the end of the template:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="html:collapse"&gt;&lt;br /&gt;&amp;lt;link href='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Styles/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shCore.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushCSharp.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushPhp.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushJScript.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushJava.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushVb.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushSql.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushXml.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushDelphi.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushPython.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushRuby.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushCss.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript' src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushCpp.js'/&amp;gt;&lt;br /&gt;&amp;lt;script class='javascript'&amp;gt;&lt;br /&gt;//&amp;lt;![CDATA[  &lt;br /&gt; dp.SyntaxHighlighter.BloggerMode();&lt;br /&gt;&lt;br /&gt;dp.SyntaxHighlighter.ClipboardSwf = 'http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/clipboard.swf';&lt;br /&gt;dp.SyntaxHighlighter.HighlightAll('code');&lt;br /&gt;//]]&amp;gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;some posts that i read suggested that you needed to download the &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt;SyntaxHighlighter&lt;/a&gt; library and host it somewhere but since you can link to the &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt;SyntaxHighlighter&lt;/a&gt; files directly in the &lt;a href="http://syntaxhighlighter.googlecode.com/svn/"&gt;googlecode svn&lt;/a&gt;, then you don't need to get your own copy of the files hosted somewhere.  i've linked to version 1.5.1 but if you were really daring, you might even link to the trunk!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;a little bit of background for this blog&lt;/span&gt;&lt;br /&gt;i've been working with &lt;a href="http://dojotoolkit.org/"&gt;the dojo toolkit&lt;/a&gt;, &lt;a href="http://framework.zend.com/"&gt;zend framework&lt;/a&gt; and &lt;a href="http://www.doctrine-project.org/"&gt;doctrine&lt;/a&gt; for a few months now and just wanted to share some of the things i've learned and also use this blog as a placeholder that i can refer back to also.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;a little bit of background about me&lt;/span&gt;&lt;br /&gt;i'm an australian who lives in the usa.  i moved here in 2000 and i married my wife in august 2007.  my wife is pregnant and we have a baby due in january 2009.  i went to university from 1993 to 1998 and graduated with a bachelor of electrical engineering and a bachelor of information technology.  since moving to america in 2000, i have been touring with bands doing sound.  at the moment, i work for &lt;a href="http://tobymac.com/"&gt;tobymac&lt;/a&gt; and on the side i'm working on web development.  i hope to have a fancy looking web app up and running soon...&lt;br /&gt;&lt;br /&gt;stay tuned for further details.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3810921673000177425-2118567455323969287?l=neonstalwart.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neonstalwart.blogspot.com/feeds/2118567455323969287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3810921673000177425&amp;postID=2118567455323969287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2118567455323969287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3810921673000177425/posts/default/2118567455323969287'/><link rel='alternate' type='text/html' href='http://neonstalwart.blogspot.com/2008/10/first-post-syntax-highlighting.html' title='first post - syntax highlighting'/><author><name>neonstalwart</name><uri>http://www.blogger.com/profile/08203386724969565151</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://3.bp.blogspot.com/_oI3r-ygCj7M/SW-iUuHTk-I/AAAAAAAAHSw/osGUo4ycMsc/S220/Adelaide+20.JPG'/></author><thr:total>0</thr:total></entry></feed>
