<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Views From The Hill &#187; Dojo</title>
	<atom:link href="http://dustint.com/archives/tag/dojo/feed" rel="self" type="application/rss+xml" />
	<link>http://dustint.com</link>
	<description>Tales Of A (Former) SFU Computing Scientist</description>
	<lastBuildDate>Thu, 17 Jun 2010 20:14:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Greasemonkey And Dojo Integration Redux</title>
		<link>http://dustint.com/archives/206</link>
		<comments>http://dustint.com/archives/206#comments</comments>
		<pubDate>Sun, 02 May 2010 02:49:16 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=206</guid>
		<description><![CDATA[Back in 2007 I wrote a post on how to integrate Dojo with Greasemonkey. Since then, Greasemonkey has been re-written to include security and bug fixes which has broken my demo code. The problem is that the new security model doesn&#8217;t return an instance to the newly created dijit.Dialog when the constructor is called. The [...]]]></description>
			<content:encoded><![CDATA[<p>Back in 2007 I wrote a post on how to integrate Dojo with Greasemonkey.<br />
Since then, Greasemonkey has been re-written to<a href="http://commons.oreilly.com/wiki/index.php/Greasemonkey_Hacks/Getting_Started#Avoid_Common_Pitfalls"> include security and bug fixes</a> which has broken my demo code. The problem is that the new security model doesn&#8217;t return an instance to the newly created dijit.Dialog when the constructor is called. The work-around is to set the ID of the dialog, and then call dijit.byId() to get a handle to it.</p>
<p>Of course, this is going to pose problems when creating non-dijit objects, as they will all be created on the page-level scope. The work-around is likely constructing clever eval() strings, and then accessing the objects using unsafeWindow. If anyone comes up with a more elegant solution, let me know about it in the comments.</p>
<p>The following can be used to overwrite the <a href="http://dustint.com/archives/4">previous version of the user-script</a>, restoring the broken functionality as well as making use of some of the newly introduced Dojo features.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// ==UserScript==</span>
<span style="color: #006600; font-style: italic;">// @name           Dojo Integration Test</span>
<span style="color: #006600; font-style: italic;">// @namespace      test</span>
<span style="color: #006600; font-style: italic;">// @description    Proof Of Concept To Integrate Dojo And Greasemonkey</span>
<span style="color: #006600; font-style: italic;">// @include        *</span>
<span style="color: #006600; font-style: italic;">// ==/UserScript==</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> startup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	dojo <span style="color: #339933;">=</span> unsafeWindow<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;dojo&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	dijit <span style="color: #339933;">=</span> unsafeWindow<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;dijit&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
	dojo.<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span>dojo.<span style="color: #660066;">body</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'tundra'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	dojo.<span style="color: #660066;">require</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dijit.Dialog&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">//Don't do anything until &quot;Dijit.Dialog&quot; has been loaded</span>
	dojo.<span style="color: #660066;">addOnLoad</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">//Actually Create The Dialog</span>
		<span style="color: #003366; font-weight: bold;">new</span> dijit.<span style="color: #660066;">Dialog</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
			id<span style="color: #339933;">:</span> <span style="color: #3366CC;">'test'</span><span style="color: #339933;">,</span>
			title<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Dojo Integration Test&quot;</span><span style="color: #339933;">,</span>
			content<span style="color: #339933;">:</span> <span style="color: #3366CC;">'Dojo lives... In Greasemonkey'</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		dijit.<span style="color: #660066;">byId</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'test'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">//include flags to djConfig to tell dojo its being used after its been loaded</span>
unsafeWindow.<span style="color: #660066;">djConfig</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
	afterOnLoad<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
	addOnLoad<span style="color: #339933;">:</span> startup
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">//Include Dojo from the AOL CDN</span>
<span style="color: #003366; font-weight: bold;">var</span> script <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'script'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
script.<span style="color: #660066;">src</span><span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;http://o.aolcdn.com/dojo/1.4/dojo/dojo.xd.js.uncompressed.js&quot;</span><span style="color: #339933;">;</span>
document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'head'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>script<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">//Include the Tundra Theme CSS file</span>
<span style="color: #003366; font-weight: bold;">var</span> link <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'link'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
link.<span style="color: #660066;">rel</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;stylesheet&quot;</span><span style="color: #339933;">;</span>
link.<span style="color: #660066;">type</span><span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;text/css&quot;</span><span style="color: #339933;">;</span>
link.<span style="color: #660066;">href</span><span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;http://o.aolcdn.com/dojo/1.4/dijit/themes/tundra/tundra.css&quot;</span><span style="color: #339933;">;</span>
document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'head'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>link<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/206/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Inject Dojo Bookmark</title>
		<link>http://dustint.com/archives/170</link>
		<comments>http://dustint.com/archives/170#comments</comments>
		<pubDate>Tue, 08 Sep 2009 19:12:36 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=170</guid>
		<description><![CDATA[Sometimes it can be handy to inject Dojo into pages that would not otherwise have it. I&#8217;ve used this so I can use dojo.query() on a page to select DOM objects while testing a parser in a different language. Use drag this link into your bookmarks and have Dojo at your fingertips no matter where [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it can be handy to inject Dojo into pages that would not otherwise have it. I&#8217;ve used this so I can use dojo.query() on a page to select DOM objects while testing a parser in a different language.</p>
<p>Use drag this link into your bookmarks and have Dojo at your fingertips no matter where your browser takes you:<br />
<a href="javascript:(function(){djConfig={afterOnLoad:true};e=document.createElement('script');e.type='text/javascript';e.src='http://o.aolcdn.com/dojo/1.3.2/dojo/dojo.xd.js';document.getElementsByTagName('head')[0].appendChild(e);})()">Inject Dojo v.1.3.2</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/170/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend JSON-RPC with Dojo Howto</title>
		<link>http://dustint.com/archives/20</link>
		<comments>http://dustint.com/archives/20#comments</comments>
		<pubDate>Tue, 03 Jun 2008 02:50:54 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[RPC]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=20</guid>
		<description><![CDATA[I have been using the Dojo toolkit as my Javascript library of choice since back in early 2006 when it was still around version 0.4. Since then, the project has made tremendous strides including the release of version 1.0 and 1.1 with 1.2 on the way. At the beginning of 2008 I started using the [...]]]></description>
			<content:encoded><![CDATA[<p><!--[if !mso]></p>
<style>
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<p><![endif]--><!--[if gte mso 9]><xml> Normal   0   false            false   false   false      EN-CA   X-NONE   X-NONE                                                     MicrosoftInternetExplorer4 </xml><![endif]--><!--[if gte mso 9]><xml> </xml><![endif]--> <!--[if gte mso 10]></p>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<p><![endif]--></p>
<p>I have been using the Dojo toolkit as my Javascript library of choice since back in early 2006 when it was still around version 0.4. Since then, the project has made tremendous strides including the release of version 1.0 and 1.1 with 1.2 on the way. At the beginning of 2008 I started using the Zend Framework to build MVC PHP applications and, with the release of 1.5, it has become my PHP framework of choice.</p>
<p>To my delight, the Zend Framework and Dojo have recently <a href="http://dojotoolkit.org/2008/05/21/announcing-zend-framework-integration-dojo-1-x-0">announced</a> a partnership which will lead to tighter integration of these two great open source frameworks.</p>
<p>One of the most exciting additions to the Zend Framework is the <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Json_Server+to+support+JSON-RPC">Zend_Json_Server support for JSON-RPC</a>. I have been using JSON-RPC with Dojo for quite some time and, up until now, it has been challenging to find a design pattern that plays nice with the Model View Controller implementation in the Zend Framework. However, with the addition of the Zend_Json_Server this is no longer the case.<span id="more-20"></span></p>
<h2>Prerequisites:</h2>
<p>This tutorial assumes you are familiar with developing in PHP and javascript and are experienced with dojo and the Zend Framework using the MVC paradigm.</p>
<h2>Common Pitfalls</h2>
<ul class="unIndentedList">
<li> Absolute paths are used in the code examples. Ensure that you modify them to reflect your server&#8217;s directory structure. This tutorial assumes that you are working with a ZF project whose /html/ directory corresponds to the root of your webserver</li>
<li> Ensure you place a .htaccess file in /html/scripts/ that disables the re-write engine. If you fail to do this step, when trying to load dojo libraries, ZF will be trying to find controllers that match the requests and throwing exceptions.</li>
</ul>
<h2>Patching Zend Framework</h2>
<p>At the time of writing, the Json-RPC component has not been accepted into the Zend Framework (although it will be soon). To get the Zend Framework (ZF) working with Json-RPC we must download code from the incubator area of SVN. If you don&#8217;t know how to use a SVN client to check out code, read about it <a href="http://framework.zend.com/manual/en/introduction.installation.html">here</a>. Download the current version of ZF and then, using an SVN client, download <a href="http://framework.zend.com/svn/framework/standard/incubator/library/Zend/Json/">http://framework.zend.com/svn/framework/standard/incubator/library/Zend/Json/ </a>and place it in the json directory of your local copy of ZF.</p>
<h2>Setting up the Directories</h2>
<p>For the purpose of this tutorial I will be using code and examples from <a href="../../../../../nickel">Nickel</a>: the application that will eventually run SFU Bookswap V.3. I use a fairly standard MVC directory structure as recommended by the ZF docs:</p>
<pre>application
	|-default
	|-controllers
	|-views
html
	|-images
	|-scripts
		|-nickel
			|-RPC
library
	|-Nickel
		|-Models
		|-RPC
	|-Zend
		| .... Framework checkout
</pre>
<p>The reasoning behind placing the Nickel folder in the library is so we can use Zend_Loader to load classes on demand. Also, as a condition of this, the classes in the Nickel folder follow the ZF naming convention: so, say, the class for a book model would be named, Nickel_Model_Book.</p>
<p>Similarly, there is a corresponding directory structure in the scripts folder. This is to be used with the Dojo packaging system. So, to access the RPC handle for the book model we would call a function such as nickel.rpc.book.getAuthor()</p>
<h2>Creating the RPC Controller</h2>
<p>The next step is to actually create the RPC controller. I have created a file in /application/default/controllers/RpcController.php which contains the RpcController action controller class. RpcController has two actions: one which will return the SMD (simple method declaration) to dojo when the JSON-RPC object is instantiated. The second action, the service action, actually processes the RPC request and returns the result. So, we have:</p>
<pre>/application/default/controllers/RpcController.php
[php]<?php
class RpcController extends Zend_Controller_Action {

	public function smdAction(){
		$class = $this->_getParam('class');

		$server = new Zend_Json_Server();

		$server->getServiceMap()->setDojoCompatible(true);
		$server->getServiceMap()->setTransport('POST')
       		->setTarget($this->getHelper('url')->url(array('controller'=>'rpc', 'action'=>'service')))
       		->setId($this->getHelper('url')->url(array('controller'=>'rpc', 'action'=>'service'))); 

       	$server->setClass($class);

       	$this->view->data = $server->getServiceMap();
		$this->render('service');
	}

	public function serviceAction(){
		$class = $this->_getParam('class');

		$server = new Zend_Json_Server();
		$server->setClass($class);
		$server->setAutoEmitResponse(true);

		$server->handle();
	}
}[/php]
</pre>
<p>The smd Action takes ‘class&#8217; as a parameter. This is the name of the class that we wish to expose via Json-RPC, such as Nickel_Rpc_Book. Please note the function call setDojoCompatible(true) which forces the server to generate dojo-compatible SMD definitions. The target function call sets the target of the function calls (the service url) to the service action defined below.</p>
<p>The service action simply processes the RPC request by calling the specified function with the sent parameters.</p>
<p>There is a fairly large security hole opened by this implementation. Since any value can be passed to the ‘class&#8217; argument, it is possible to remotely call functions for any class that can be auto-loaded. A ‘safer&#8217; implementation would simply concatenate the class parameter with &#8220;Nickel_Rpc_&#8221;. This way is less likely that an attacker could compromise your server by calling a dangerous function.</p>
<h2>Writing a RPC Class</h2>
<p>Now that we have the RPC server set up we need some classes in Nickel_RPC to call. For the purpose of this example we will use a very simple Book class that has basic functionality:</p>
<pre>/library/Nickel/Model/Book.php
[php]<?php
class Nickel_RPC_Book {
	public static function simpleEcho(){
		return “Hello World”;
	}
	public static function getTitle($bookId){
		$book = new Nickel_Model_Book($bookId);
		return $book->getTitle();
	}
	public static function setTitle($bookId, $title){
		$book = new Nickel_Model_Book($bookId);
		$book->setTitle($title);
		$book->update();
		return true;
	}
}
[/php]</pre>
<p>In the above RPC class, in addition to the simpleEcho function, we have two static functions: one that reads the title from the Book Model, and the second which writes a new title back to the database via the Book model. Notice that the functions are static: this is because, in the case of our book anyways, a notion of $this doesn&#8217;t really make since, as we don&#8217;t actually know what book we want the title for unless we pass the book ID from dojo.</p>
<h2>Writing the RPC Front-end</h2>
<p>Now that we have the backend written, it is fairly quick to write the frontend.</p>
<p>The first step is to create the book rpc file so we can include nickel.rpc.book using a dojo.require statement:</p>
<pre>/html/scripts/nickel/RPC/book.js
[js]dojo.provide(‘nickel.rpc.book’);
dojo.require(‘dojo.rpc.JsonService’);

nickel.rpc.book = new dojo.rpc.JsonService(‘/rpc/smd/class/Nickel_RPC_Book’);
[/js]</pre>
<p>The above code snippet should be saved as book.js and placed in /html/scripts/nickel/rpc. When this file is included, a new JsonService object is created with functions populated from the SMD generated by the RPC controller class. As a result, nickel.rpc.book will now contain three functions: simpleEcho, getTitle and setTitle.</p>
<h2>Using The Front-end.</h2>
<p>Finally, we have the opportunity to see the fruit of our labour. Create an indexController and the accompanying view. In the view, after including dojo.js, create a new script block:</p>
<pre>/application/default/views/index/index.phtml
...
[js]<script type=”text/javascript”>
	dojo.registerModulePath(‘nickel’, ‘/scripts/nickel’);
	dojo.require(‘nickel.rpc.book’);

	dojo.addOnLoad(function(){
		nickel.rpc.book.simpleEcho().addCallback(function(msg){
			alert(msg);		//Alert: Hello World
	});

	nickel.rpc.book.getTitle(1).addCallback(function(title){
		alert(title);	//Alert: title of book with ID 1 in database
	});

	nickel.rpc.book.setTitle(1, ‘Foo’).addCallback(function(result){
		alert(‘success’);	//Sets the title of book with ID 1 to ‘Foo’
	});
});
</script>
...
[/js]</pre>
<p>dojo.registerModulePath adds a module path to the dojo loader. This allows us to include our custom nickel modules easily and on-demand.</p>
<h2>Conclusion</h2>
<p>The Dojo Toolkit and Zend Framework provide a highly structured, maintainable JSON RPC system when used together. This can be used to easily propagate dirty javascript data objects to persistent storage in the backend, as well as expose PHP function calls to javascript to return useful data.</p>
<p>I hope you have enjoyed this tutorial. If you find any typos, mistakes or just wish to leave a message, please add a comment below.</p>
<p>I also encourage you to link to this post if you have found it at all useful in developing your web-application.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/20/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Automatically Require Dijit Widgets</title>
		<link>http://dustint.com/archives/14</link>
		<comments>http://dustint.com/archives/14#comments</comments>
		<pubDate>Sun, 16 Mar 2008 18:47:42 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Dijit]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[Widget]]></category>

		<guid isPermaLink="false">http://dustint.com/archives/14</guid>
		<description><![CDATA[Recently I have been playing with the dojox.dtl: the javascript port of the Django templating engine. So far I am quite impressed, not only is it fast and full featured, but by writing a wrapper class it is easy to make it behave like server side templating systems: you specify a template and pass it [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been playing with the dojox.dtl: the javascript port of the <a href="http://www.djangoproject.com/documentation/templates/" target="_blank">Django templating engine</a>. So far I am quite impressed, not only is it fast and full featured, but by writing a wrapper class it is easy to make it behave like server side templating systems: you specify a template and pass it an object and it will render that object according to the template rules.</p>
<p>The only trouble I ran into was when I wanted to used Dijit Widgets in my templates. Since on my main page I didn&#8217;t know what template I would be calling, I didn&#8217;t know which Widget classes to include with dojo.require(). To fix this, I have come up with a little hack that does the job, although not too elegantly.</p>
<p>Bascially my approach includes hooking into dojo.parser and changing its behaviour. Now when it is parsing widgets from the page it checks to see if they exist and, if not, it does the appropriate dojo.require() to try to pull them in.</p>
<blockquote>
<pre>var fn = dojo.parser.instantiate;</pre>
<pre>
dojo.parser.instantiate = function(nodes){</pre>
<pre>    dojo.forEach(nodes, function(node){</pre>
<pre>        var className = node.getAttribute(dojo._scopeName + "Type")</pre>
<pre>        if(!dojo.isFunction(dojo.getObject(className))){</pre>
<pre>            //It is not an object... yet</pre>
<pre>            dojo.require(className);</pre>
<pre>        }</pre>
<pre>    });</pre>
<pre>    return fn(nodes);</pre>
<pre>}</pre>
</blockquote>
<p>The above code-block shows the implimentation. Simply place this in between &lt;script&gt; tags in your header. Now you should be able to do dojotypes anywhere on your page and have the appropriate classes automatically included.</p>
<p>There are several disadvantages to my approach. For example, if you have a typo in one of your  dojoType, it will try to pull down a file that doesn&#8217;t exist. We also have the impact of running through the array of nodes an additional time, although since the dojo.parser.instantiate function is already bounded by O(n) this shouldn&#8217;t make a noticeable impact.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/14/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dojo: Meet Google Book Search</title>
		<link>http://dustint.com/archives/11</link>
		<comments>http://dustint.com/archives/11#comments</comments>
		<pubDate>Sat, 12 Jan 2008 10:19:43 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[How-To]]></category>
		<category><![CDATA[Book Search]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=11</guid>
		<description><![CDATA[For those of you who read about the re-launching of the SFU Bookswap website (http://sfubookswap.com), you may remember that one of the new features was the integration of the Google Books database. In this entry I am going to talk about how I integrated the Google Book Search functionality into my existing Dojo framework. First [...]]]></description>
			<content:encoded><![CDATA[<p>For those of you who read about the re-launching of the SFU Bookswap website (<a href="http://sfubookswap.com">http://sfubookswap.com</a>), you may remember that one of the new features was the integration of the Google Books database.<br />
In this entry I am going to talk about how I integrated the Google Book Search functionality into my existing Dojo framework.</p>
<p>First things first: you need to sign up for a Google AJAX Search API key. You can get your key, as well as a description of the API and documentation from Google here: <a href="http://code.google.com/apis/ajaxsearch/signup.html">http://code.google.com/apis/ajaxsearch/signup.html</a>.</p>
<p>Google offers a Search container, which allows the integration of several search sources, including the web, images, blogs, news items and books. I only wanted the Book source so I chose to take the simple route and not use the container class. Instead I used the GbookSearch object directly, which allows me to access the data more easily as well as utilize only the desired functionality.</p>
<p>The very first step in integrating the Google Books search results is including the Google class on your page:</p>
<blockquote>
<pre>&lt;script type="text/javascript" src="http://www.google.com/jsapi?key=&lt;yourapikey&gt;"&gt;&lt;/script&gt;</pre>
</blockquote>
<p>Next, we need to ensure that the Google Search namespace is loaded so we have access to the searching functions. This is as simple as including script tags with the following</p>
<blockquote>
<pre>google.load("search","1");</pre>
</blockquote>
<p>Because objects are swell, and will allow us to instantiate multiple searches on the same page, we are going to encapsulate the Google Book Search object in a wrapper object which exposes only the functionality we desire.</p>
<blockquote>
<pre>dojo.declare("GoogleBookSearch", null, {
    constructor: function(){
		this._bookSearch = new GbookSearch();
		this._bookSearch.setNoHtmlGeneration();
		dojo.connect(GbookSearch,"RawCompletion",this,"resultCallback");
    },
    query: function(q){
        this._bookSearch.execute(q);
    },
    resultCallback: function(){
    	console.debug("Got Data Back, Lets Take A look:");
    	console.dir(this._bookSearch.results);
    	for(var x=0; x&lt;this._bookSearch.results.length; x++){
    		document.body.appendChild(this._bookSearch.results[x].html);
    	}
    },
    goToPage: function(p){
    	this._bookSearch.gotoPage(p);
    },
    getNextPage: function(){
    	this._bookSearch.gotoPage(this._bookSearch.cursor.currentPageIndex+1);
    }
});</pre>
</blockquote>
<p>The first line of this class (the dojo.declare) creates a new GoogleBookSearch object, which does not inherit from any object (the null parameter), which has several functions and attributes.</p>
<h3>The Constructor Function:</h3>
<p>The constructor function sets up the search object by creating a new GbookSearch instance. To gain a slight speed improvement, we disable HTML generation, which will prevent the GbookSearch class from downloading images and generating Google&#8217;s HTML representation of the search results. Finally we connect the “RawCompletion” event that is fired by the GbookSearch object to a callback function in the local object. After every search query is completed, this event is fired by the global object.</p>
<p>The rest of the functions are fairly self explanatory: the query function accepts one argument, which is the query from the user. The query can be an ISBN, author, title or any other combination of book properties that Google stores in their book database. The resultCallback function processes the data after the GbookSearch class has received search results from the server. Notice that they do not come in the form as an argument to the function but, rather, are accessed by iterating through the _bookSearch.results array. The gotoPage and getNextPage move to the next page of search results (as only 4 are returned by default). No other code is needed, as after getting the results for the next page, the “RawCompletion” event is fired once again.</p>
<p>To use your shiny new class, simply instantiate it after the page has loaded. So, for example:</p>
<blockquote>
<pre>dojo.addOnLoad(function(){
    myBookSearch = new GoogleBookSearch();
});</pre>
</blockquote>
<p>Make sure you don&#8217;t put a var in front of bookSearch, otherwise the object will have only local visibility, and be removed after the function has executed.</p>
<h2>Tips and Tricks:</h2>
<h3>Modifying the callback function.</h3>
<p>In my case, I wanted to have a default callback function that is executed when the search results are returned. However, I wanted separate instances of the GoogleBookSearch object to handle search results differently. To do this, we want to “overload” the resultCallback function using dojo&#8217;s hitch functionality.</p>
<blockquote>
<pre>dojo.addOnLoad(function(){
    myBookSearch = new GoogleBookSearch();
    myBookSearch.resultCallback = dojo.hitch(this,function(){
        if( myBookSearch._bookSearch.results.length&gt;0){
           alert('Showing '+myBookSearch ._bookSearch.results.length+' of '+ myBookSearch._bookSearch.cursor.estimatedResultCount +' Results');
        }
    });
});</pre>
</blockquote>
<p>The dojo.hitch function accepts two arguments, a function or method name as the second argument, and the scope in which the method executes as the first argument. It is crucial that this scope is set correctly as the default behaviour is to execute in the scope of the GoogleBookSearch object which may be ok if only global or Google BookSearch attributes and functions are used, but is insufficient if we are wrapping the GoogleBookSearch object inside another object and want the callback to be defined as a function in the outer object.</p>
<h3>Cleaning Up The Results</h3>
<p>When returning the results, if any of the attributes of the book were a keyword in the search, for example, the author field contained a keyword, then the keyword in the author field would be enclosed in bold tags. In my application I am importing data into a database so I want it to be as clean as possible. My solution is using a regular expression to remove all HTML tags. For example</p>
<blockquote>
<pre>myBookSearch._bookSearch.results[0].authors.replace(/(&lt;([^&gt;]+)&gt;)/ig,"")</pre>
</blockquote>
<h3>Extracting the image of the book cover</h3>
<p>You may notice that the book covers are dynamically generated for each query and expire after a short time. My workaround for this is to use regular expressions to parse out the book ID and then use the same (permanent) address that Google does when displaying the book covers on the book details page.<br />
This can be accomplished as follows:</p>
<blockquote>
<pre>var imgUrl = "http://books.google.com/books?id="+/.*id=([^&amp;]*)/g.exec(myBookSearch._bookSearch.results[0].tbUrl)[1]+"&amp;printsec=frontcover&amp;img=1&amp;zoom=1"</pre>
</blockquote>
<p>The regular expression extracts the book ID from the thumbnail URL and combines it with the persistent book cover URL</p>
<p>There are a bunch of other attributes stored by the GbookSearch object. Look in the Google API to see a bunch of them or, alternatively, use Firebug to snoop the object after results have been returned.</p>
<p>Happy Coding!</p>
<p>External Links<br />
Google AJAX Search: <a href="http://code.google.com/apis/ajaxsearch/">http://code.google.com/apis/ajaxsearch/</a><br />
Google AJAX Search API: <a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html">http://code.google.com/apis/ajaxsearch/documentation/reference.html</a><br />
Firebug: <a href="http://www.getfirebug.com/">www.getfirebug.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/11/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Greasemonkey And Dojo Integration</title>
		<link>http://dustint.com/archives/4</link>
		<comments>http://dustint.com/archives/4#comments</comments>
		<pubDate>Sun, 18 Nov 2007 22:35:11 +0000</pubDate>
		<dc:creator>Dustin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://dustint.com/?p=4</guid>
		<description><![CDATA[Dojo (http://dojotoolkit.org/) is a wonderful javascript toolkit which just reached version 1.0 at the beginning of November. I have been watching and developing with Dojo for a couple years now and I can&#8217;t tell you how excited I am to have passed the version 1 milestone Greasemonkey (http://www.greasespot.net/) is a handy Firefox extension which allows [...]]]></description>
			<content:encoded><![CDATA[<p>Dojo (<a href="http://dojotoolkit.org/" title="Dojo Toolkit" target="_blank">http://dojotoolkit.org/</a>) is a wonderful javascript toolkit which just reached version 1.0 at the beginning of November. I have been watching and developing with Dojo for a couple years now and I can&#8217;t tell you how excited I am to have passed the version 1 milestone</p>
<p>Greasemonkey (<a href="http://www.greasespot.net/" title="Greasemonkey">http://www.greasespot.net/</a>) is a handy Firefox extension which allows the injection of javascript (called userscripts) into the webpage currently being viewed. This allows for the customization of the look and feel of a website: improving the user interface or adding additional functionality.</p>
<p>In this example, we are going to use greasemonkey and Dojo to display a dialog widget on an arbitrary website.</p>
<p>To simplify the deployment of a userscript we are going to use the AOL Content Distribution Network to pull in a crossdomain build of the dojo toolkit. This is helpful to us as developers as we don&#8217;t have to build or maintain Dojo ourselves and is useful to the user as they get an optimized download from a distributed CDN.</p>
<p>First thing&#8217;s first: If you haven&#8217;t already, download and install the Greasemonkey extension, and create a new user script.</p>
<p>To access the power of Dojo, we must include the Dojo crossdomain build on the page we are visiting. To do this, we will dynamically create a new script element containing the address of the build and append it to the document head:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> script <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'script'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
script.<span style="color: #660066;">src</span><span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js&quot;</span><span style="color: #339933;">;</span>
document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'head'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>script<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Next, since we are going to need a Dijit Dialog object, we will need to also include the Tundra Theme CSS file by appending it to the head object:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> link <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'link'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
link.<span style="color: #660066;">rel</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;stylesheet&quot;</span><span style="color: #339933;">;</span>
link.<span style="color: #660066;">type</span><span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;text/css&quot;</span><span style="color: #339933;">;</span>
link.<span style="color: #660066;">href</span><span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css&quot;</span><span style="color: #339933;">;</span>
document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'head'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>link<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Great! Now we have the Dojo javascript file included on the page as well as the Dijit Tundra theme setup and ready to use. Next, we will actually include the Dojo dependencies we need and display our Dialog!</p>
<p>To ensure that the Dojo Javascript file and the Tundra Stylesheet  have been downloaded and parsed we must include the rest of the code in a function that will run when the window fires the &#8220;load&#8221; event To do this, we will add an event listener to the window object with the function as an argument:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">window.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'load'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #003366; font-weight: bold;">var</span> dojo <span style="color: #339933;">=</span>  unsafeWindow<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;dojo&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
dojo.<span style="color: #660066;">require</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dijit.Dialog&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Also notice that we have created a local variable called Dojo which is a refrence to the unsafeWindow dojo object. Greasemonkey runs all userscripts in a sandbox which provides enhanced security as well as ensures that they do not conflict with any preexisting scripts already on the page. Because, by default, Dojo is instantiated with a visibility relative to the window object it is not visible to our script. By creating a reference to it in a local variable, this allows us to access its functionality.</p>
<p>Also important is the dojo.require statement. This will pull in the dijit.Dialog object which we will be instantiating later on in our script. To ensure that all the dependences have been loaded before we try to create a dialog, we must wait until dojo knows that the external resource has been loaded.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">dojo.<span style="color: #660066;">addOnLoad</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #003366; font-weight: bold;">var</span> dijit <span style="color: #339933;">=</span> unsafeWindow<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;dijit&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
dojo.<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'body'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;tundra&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> pane <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'div'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
pane.<span style="color: #660066;">id</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;floatingPane&quot;</span><span style="color: #339933;">;</span>
pane.<span style="color: #660066;">innerHTML</span><span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;Dojo Lives... In GreaseMonkey!&quot;</span><span style="color: #339933;">;</span>
document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'body'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>pane<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
dialog <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> dijit.<span style="color: #660066;">Dialog</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
title<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Dojo Integration Test&quot;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>pane<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
dialog.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'false'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>A lot of stuff happens in the above code snippit:<br />
First we grab a local reference to the global dijit object, next we assign a &#8220;tundra&#8221; class to the body tag, which will allow us to have the correct theme for our Dialog. We create a div node which will eventually become our Dialog, populate it with appropriate attributes and append it to the document&#8217;s body tag. Finally we create a new dialog object with a catchy title and the previously created div node as the contents, and display it on screen. Lastly, we close the window.addEventListener object that we created in the previous step.</p>
<p>Downloaded the complete userscript here:<br />
<del datetime="2010-05-02T02:12:43+00:00"><a href="http://dustint.com/code/dojointegrationtest.user.js">Dojo Integration Userscript</a></del> This script has been updated and is available <a href="http://dustint.com/archives/206">here</a></p>
<p>Special Thanks to Shane Sullivan&#8217;s <a href="http://userscripts.org/scripts/show/9424">Dojo Debug Script</a> which shows how to access the Dojo object from the Greasemonkey sandbox.</p>
]]></content:encoded>
			<wfw:commentRss>http://dustint.com/archives/4/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
