<?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>REVERT TO CONSOLE &#187; Javascript</title>
	<atom:link href="http://www.reverttoconsole.com/blog/category/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.reverttoconsole.com</link>
	<description>for f in *;do echo &#124; sed &#039;i\rtc&#039; &#62;&#62; $f;done; java programming et al</description>
	<lastBuildDate>Thu, 25 Aug 2011 15:02:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>JavaScript Null Checks and Type Coercion</title>
		<link>http://www.reverttoconsole.com/blog/javascript/javascript-null-checks-and-type-coercion/</link>
		<comments>http://www.reverttoconsole.com/blog/javascript/javascript-null-checks-and-type-coercion/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 17:52:23 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.reverttoconsole.com/?p=418</guid>
		<description><![CDATA[There are many discussions of JavaScripts type coercion at work, and many examples of the distinction between undefined and null. This becomes very important when performing checks for null and undefined. Here&#8217;s an easy summary: JavaScript distinguishes between null, which is an object of type &#8216;object&#8217; that indicates a deliberate non-value, and undefined, which is an object [...]]]></description>
			<content:encoded><![CDATA[<p>There are many discussions of JavaScripts type coercion at work, and many examples of the distinction between undefined and null. This becomes very important when performing checks for null and undefined.</p>
<p>Here&#8217;s an easy summary:</p>
<p>JavaScript distinguishes between <code style="color: #25221d; font-weight: inherit;"><strong>null</strong></code>, which is an object of type &#8216;object&#8217; that indicates a deliberate non-value, and <code style="color: #25221d; font-weight: inherit;"><strong>undefined</strong></code>, which is an object of type &#8216;undefined&#8217; that indicates an uninitialized value.</p>
<p>While this distinction is made, undefined == null. This is due to JavaScripts type coercion. The two operands do NOT have to be of the same type to yield true for equality, as JavaScript automatically performs conversion on a differing operand.</p>
<p>So:</p>
<ul>
<li>1==true  // evaluates to true</li>
<li>&#8220;1&#8243;==true // evaluates to true</li>
<li>45==&#8221;45&#8243; // evaluates to true</li>
<li>null==undefined // evaluates to true</li>
</ul>
<p>If the last bullet doesn&#8217;t seem to make as much sense, you&#8217;re not alone.</p>
<p>In a lot of cases, you&#8217;re not going to want to evaluate objects with this coercion. For those cases, strict evaluation is allowed with ===. No coercion is performed in this case.</p>
<p>So:</p>
<ul>
<li>true===1  // evaluates to false</li>
<li>NaN===NaN // evaluates to false</li>
<li>var x=[1,2]</li>
<li>var y=[1,2]</li>
<li>x===y // evaluates to false</li>
<li>undefined === null // evaluates to false</li>
</ul>
<p>var healthCare = {<br />
  exists: true<br />
};</p>
<p>healthCare.exists  // will be true<br />
healthCare.isExpensive // will be undefined</p>
<p>Lastly, double negation can be used in JavaScript to convert any value to a Boolean object.</p>
<p>if(!!healthCare.exists)  // will be true</p>
<p>if(!!healthCare.isExpensive) // will be false</p>

<span class="slashdigglicious">
<a href="http://slashdot.org/bookmark.pl?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F&amp;title=JavaScript+Null+Checks+and+Type+Coercion" title="Slashdot It!"><img src="http://slashdot.org/favicon.ico" height="16" width="16" alt="[Slashdot]" /></a>
<a href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F&amp;title=JavaScript+Null+Checks+and+Type+Coercion" title="Digg This Story"><img src="http://digg.com/favicon.ico" width="16" height="16" alt="[Digg]" /></a>
<a href="http://reddit.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F&amp;title=JavaScript+Null+Checks+and+Type+Coercion" title="Reddit"><img src="http://reddit.com/favicon.ico" width="16" height="16" alt="[Reddit]" /></a>
<a href="http://del.icio.us/post?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F&amp;title=JavaScript+Null+Checks+and+Type+Coercion" title="Save to del.icio.us" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F&amp;title=JavaScript+Null+Checks+and+Type+Coercion', 'delicious', 'toolbar=no,width=700,height=400'); return false;"><img src="http://images.del.icio.us/static/img/delicious.small.gif" width="16" height="16" alt="[del.icio.us]" /></a>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F" title="Share on Facebook"><img src="http://www.facebook.com/favicon.ico" width="16" height="16" alt="[Facebook]" /></a>
<a href="http://technorati.com/faves?add=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F" title="Add to my Technorati Favorites"><img src="http://technorati.com/favicon.ico" width="16" height="16" alt="[Technorati]" /></a>
<a href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F&amp;title=JavaScript+Null+Checks+and+Type+Coercion" title="Save to Google Bookmarks"><img src="http://www.google.com/favicon.ico" width="16" height="16" alt="[Google]" /></a>
<a href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fjavascript-null-checks-and-type-coercion%2F&amp;title=JavaScript+Null+Checks+and+Type+Coercion" title="Stumble it!"><img src="http://www.stumbleupon.com/favicon.ico" width="16" height="16" alt="[StumbleUpon]" /></a>
</span>]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/javascript/javascript-null-checks-and-type-coercion/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Integrating JavaScript Tests with Continuous Integration</title>
		<link>http://www.reverttoconsole.com/blog/javascript/integrating-javascript-tests-with-continuous-integration/</link>
		<comments>http://www.reverttoconsole.com/blog/javascript/integrating-javascript-tests-with-continuous-integration/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 08:35:21 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.reverttoconsole.com/?p=384</guid>
		<description><![CDATA[At my current client I&#8217;ve been building a rather complex rich client app using ExtJs. The team has written a lot of JavaScript code, and has been writing a lot of JavaScript unit tests as well. We&#8217;ve gone through several unit testing tools along the way trying to solve some logistical problems. We started with [...]]]></description>
			<content:encoded><![CDATA[<p>At my current client I&#8217;ve been building a rather complex rich client app using ExtJs. The team has written a lot of JavaScript code, and has been writing a lot of JavaScript unit tests as well.</p>
<p>We&#8217;ve gone through several unit testing tools along the way trying to solve some logistical problems. We started with <a href="http://www.jsunit.net/">JSUnit</a>, added <a href="http://seleniumhq.org">Selenium</a>, switched from <a href="http://www.jsunit.net/">JSUnit</a>t to <a href="http://groups.google.com/group/envjs?pli=1">envjs</a>, and are now using a hybrid approach I&#8217;ll describe in detail.</p>
<p>Some of the issues we wanted to address with our testing tools were:</p>
<ul>
<li>How easy is it to run the tests?</li>
<li>How easy is it to debug the tests?</li>
<li>How easy is it to integrate the tests into our existing continuous integration environment</li>
</ul>
<p>Most of the tools we used easily met the first two logistical issues, but the last one was not as simple.</p>
<p>The following describes an approach that meets all of the above list (after the jump).</p>
<p><span id="more-384"></span></p>
<p>Here is a very simple JavaScript object to test and illustrate the example:</p>
<pre lang="javascript" line="1">
var swineFluIndicator = {
  hasSwineFlu: function(sample) {
    return !!sample.oink ? true : false;
  }
};
</pre>
<p>If the sample has a property &#8220;oink&#8221;, the sample is infected with swine flu. Simple.</p>
<p>To test our code in development, we used the <a href="http://github.com/nkallen/screw-unit/tree/master">Screw.Unit</a> test framework.</p>
<p>We went with Screw.Unit for several reasons:</p>
<ul>
<li>Simple to implement- It&#8217;s just a JavaScript library</li>
<li>It generates a simple DOM output, which makes integration easy &#8211; I&#8217;ll demonstrate later.</li>
<li>It&#8217;s easy to customize, and the framework does not pollute the global namespace at all.</li>
<li>It&#8217;s simple to run and debug.</li>
</ul>
<p>Here is an example Screw.Unit test of the sample code:</p>
<pre lang="javascript" line="1">
Screw.Unit(function() {
  describe("test whether a given sample has swine flu", function() {
   it("clean sample", function() {
     var swineFluIndicator  = new SwineFluIndicator();
     var testSample = {
       value : '123'
     };
      expect(swineFluIndicator.hasSwineFlu(testSample)).to(be_false);
    });
  });
});
</pre>
<p>Screw.Unit tests are executed in the browser (so debugging with <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a> is easy, and produce a very simple DOM that&#8217;s simple to read:<br />
<img src="http://s3.amazonaws.com/assets.pivotallabs.com/87/original/runner.png" alt="Screw.Unit Runner" /></p>
<p>Writing JavaScript unit tests is pretty easy; now it&#8217;s time to integrate them. <a href="http://htmlunit.sourceforge.net/">HtmlUnit</a> have released 2 new versions in 2009 so far that offer unprecedented DOM support via Rhino. With HtmlUnit, our test consists of rendering the page and interpreting the simple DOM results.</p>
<p>Set up the clients and load the page:</p>
<pre lang="java" line="1">
WebClient firefoxClient = new WebClient(BrowserVersion.FIREFOX_2);
WebClient ieClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_6);

firefoxClient.setThrowExceptionOnScriptError(true);
ieClient.setThrowExceptionOnScriptError(true);
HtmlPage htmlPage = (HtmlPage) client.getPage(testFile.toURL());</pre>
<p>and provide a means of interpreting the page results:</p>
<pre lang="java" line="1">
protected void interpretTestResults(final HtmlPage htmlPage) {
        String header = "";
        String heading = "";
        String paragraph = "";
        // returns a list of tests
        List testDivs = (List) htmlPage
            .getByXPath("//*[contains(@class,'describe focused')]");

        for (HtmlListItem htmlListItem : testDivs) {
            List heading1List = (List) htmlListItem.getByXPath("./h1");
            header = heading1List.get(0).getTextContent();
            // returns a list of its divisions; if there are nested
            // describes, there will be multiple its
            List test = (List) htmlListItem
                .getByXPath(".//*[contains(@class,'its')]");
            for (HtmlUnorderedList htmlUnorderedList : test) {
                // if there are no child nodes, this is part of a nested
                // describe
                if (htmlUnorderedList.hasChildNodes()) {
                    List failedItemList = (List) htmlUnorderedList
                        .getByXPath(".//*[contains(@class,'it enqueued failed')]");
                    if (failedItemList.size() == 0) {
                        // successful
                    } else {
                        for (HtmlListItem failedItem : failedItemList) {
                            List describedList = (List) failedItem
                                .getByXPath("./h2");
                            Assert.assertTrue(describedList.size() == 1);
                            heading = describedList.get(0).getTextContent();
                            List errorMessageList = (List) failedItem
                                .getByXPath("./*[contains(@class, 'error')]");
                            for (HtmlParagraph htmlParagraph : errorMessageList) {
                                paragraph += htmlParagraph.getTextContent();
                            }
                        }
                        Assert.fail("Header: " + header + " heading: " + heading + " paragraph: "
                            + paragraph);
                    }
                }
            }
        }
    }</pre>
<p>This method takes an HtmlUnit HtmlPage and, using xpath expressions, iterates over the test result DIV tags generated by Screw.Unit. It ignores tests that passed, and focuses on the failed tests. For failed tests it gets the provided information about the test (the <em>it </em>and <em>describes </em>strings), so that we&#8217;ll know what test failed and why.</p>
<p>Lastly, rather than write a test for every Screw.Unit test page we write, we made use of JUnit4&#8242;s Parameterized test. This way we provide a list of Screw.Unit tests and have the Parameterized test execute a test for each.</p>
<p>Annotate the class:</p>
<pre lang="java" line="1">
@RunWith (Parameterized.class)
public class ScrewUnitTest {</pre>
<pre lang="java" line="1">
Provide a static Collection:
@SuppressWarnings ("unchecked")
    @Parameters
    public static Collection data() {
        Collection fileCollection = new ArrayList();
        Collection fileList = FileUtils.listFiles(new File(HTML_TEST_DIR), extensions, true);
        for (File file : fileList) {
            File[] fileArray = { file };
            fileCollection.add(fileArray);
        }
        return fileCollection;
    }
</pre>
<p>and a constructor:</p>
<pre lang="java" line="1">
public ScrewUnitTest(File file) {
        this.file = file;
    }</pre>
<p>Then for every file in the Collection, this.file will be available for reference in the tests. And our JavaScript tests can be easily run by a continuous integration system.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/javascript/integrating-javascript-tests-with-continuous-integration/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Unit Testing JavaScript with HtmlUnit and Screw.Unit</title>
		<link>http://www.reverttoconsole.com/blog/javascript/unit-testing-javascript-with-htmlunit-and-screwunit/</link>
		<comments>http://www.reverttoconsole.com/blog/javascript/unit-testing-javascript-with-htmlunit-and-screwunit/#comments</comments>
		<pubDate>Fri, 29 May 2009 14:30:44 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[UnitTest]]></category>

		<guid isPermaLink="false">http://www.reverttoconsole.com/blog/java/unit-testing-javascript-with-htmlunit-and-screwunit/</guid>
		<description><![CDATA[Writing apps with today&#39;s rich client libraries such as Extjs , YUI , and JQuery really shows how much potential is still left in web development. But it takes a lot of code, and the amount of technical debt can get heavy, quickly. Good tests can help reduce this technical debt, and there are a lot of testing [...]]]></description>
			<content:encoded><![CDATA[<p>Writing apps with today&#39;s rich client libraries such as <a href="http://extjs.com/">Extjs</a> , <a href="http://developer.yahoo.com/yui/">YUI</a> , and <a href="http://jquery.com/">JQuery</a> really shows how much potential is still left in web development. But it takes a lot of code, and the amount of <a href="http://en.wikipedia.org/wiki/Technical_debt">technical debt</a> can get heavy, quickly. Good tests can help reduce this technical debt, and there are a lot of testing tools available for the client. Today though, I want to go beyond just using a tool, and talk more about integrating your JavaScript tests into an existing <a href="http://en.wikipedia.org/wiki/Continuous_Integration">Continuous Integration</a> environment. 
<div></div>
<div>I have a confession to make- I hate running tests manually. I&#39;ll write tests when I&#39;m doing new development or bug fixing, but I hate running them after I&#39;ve fixed the bug or implemented the code. That&#39;s why we have CI environments, right? So I don&#39;t have to run the stupid tests each time! There are enough ridiculous rules put in place in corporate work environments today already, I don&#39;t like adding tasks that can be automated into the mix.</div>
<div></div>
<div>Here&#39;s what I&#39;ve come up with for integrating my JavaScript Unit Tests:</div>
<div></div>
<div>
<ol>
<li>Write tests with <a href="http://github.com/nkallen/screw-unit/tree/master">Screw.Unit</a> . Why Screw.Unit? I like the simple DOM it creates. I like the code behind it- specifically the separation of builders and matchers. It&#39;s relatively easy to debug my code in Firebug. But mostly, it&#39;s because it&#39;s of the easy DOM it displays. There&#39;s nothing magical about Screw.Unit. It&#39;s just a simple tool. But that&#39;s the point.</li>
<li>Use <a href="http://htmlunit.sourceforge.net/">HtmlUnit</a> to execute Screw.Unit tests, and inspect the results. HtmlUnit has the best JavaScript framework support in the Java world today. It uses <a href="http://www.mozilla.org/rhino/">Rhino</a> to execute JavaScript and has written very comprehensive DOM support on top of that. It can handle most major JS framework code. So I execute my tests with HtmlUnit, and then inspect the simple DOM results. Easy!</li>
<li>I use a <a href="http://junit.org/apidocs/org/junit/runners/Parameterized.html">Parameterized JunitTest</a> to read through all of my ScrewUnit tests (*.html files), and execute a JUnit test for each. </li>
</ol>
<div>Done! Simple integration at it&#39;s best.</div>
</p></div>
<p style="font-size: 10px;">  <a href="http://posterous.com">Posted via email</a>   </p>

<span class="slashdigglicious">
<a href="http://slashdot.org/bookmark.pl?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F&amp;title=Unit+Testing+JavaScript+with+HtmlUnit+and+Screw.Unit" title="Slashdot It!"><img src="http://slashdot.org/favicon.ico" height="16" width="16" alt="[Slashdot]" /></a>
<a href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F&amp;title=Unit+Testing+JavaScript+with+HtmlUnit+and+Screw.Unit" title="Digg This Story"><img src="http://digg.com/favicon.ico" width="16" height="16" alt="[Digg]" /></a>
<a href="http://reddit.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F&amp;title=Unit+Testing+JavaScript+with+HtmlUnit+and+Screw.Unit" title="Reddit"><img src="http://reddit.com/favicon.ico" width="16" height="16" alt="[Reddit]" /></a>
<a href="http://del.icio.us/post?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F&amp;title=Unit+Testing+JavaScript+with+HtmlUnit+and+Screw.Unit" title="Save to del.icio.us" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F&amp;title=Unit+Testing+JavaScript+with+HtmlUnit+and+Screw.Unit', 'delicious', 'toolbar=no,width=700,height=400'); return false;"><img src="http://images.del.icio.us/static/img/delicious.small.gif" width="16" height="16" alt="[del.icio.us]" /></a>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F" title="Share on Facebook"><img src="http://www.facebook.com/favicon.ico" width="16" height="16" alt="[Facebook]" /></a>
<a href="http://technorati.com/faves?add=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F" title="Add to my Technorati Favorites"><img src="http://technorati.com/favicon.ico" width="16" height="16" alt="[Technorati]" /></a>
<a href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F&amp;title=Unit+Testing+JavaScript+with+HtmlUnit+and+Screw.Unit" title="Save to Google Bookmarks"><img src="http://www.google.com/favicon.ico" width="16" height="16" alt="[Google]" /></a>
<a href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Funit-testing-javascript-with-htmlunit-and-screwunit%2F&amp;title=Unit+Testing+JavaScript+with+HtmlUnit+and+Screw.Unit" title="Stumble it!"><img src="http://www.stumbleupon.com/favicon.ico" width="16" height="16" alt="[StumbleUpon]" /></a>
</span>]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/javascript/unit-testing-javascript-with-htmlunit-and-screwunit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript Unit Testing</title>
		<link>http://www.reverttoconsole.com/blog/ajax/javascript-unit-testing/</link>
		<comments>http://www.reverttoconsole.com/blog/ajax/javascript-unit-testing/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 22:28:38 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[UnitTest]]></category>

		<guid isPermaLink="false">http://www.reverttoconsole.com/?p=328</guid>
		<description><![CDATA[TechTalk: Testing Rich Client Web Applications by Jeff Hemminger from Object Partners on Vimeo.]]></description>
			<content:encoded><![CDATA[<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="300" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=4198648&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="400" height="300" src="http://vimeo.com/moogaloop.swf?clip_id=4198648&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object><br />
<a href="http://vimeo.com/4198648">TechTalk: Testing Rich Client Web Applications by Jeff Hemminger</a> from <a href="http://vimeo.com/user1150787">Object Partners</a> on <a href="http://vimeo.com">Vimeo</a>.</p>

<span class="slashdigglicious">
<a href="http://slashdot.org/bookmark.pl?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F&amp;title=JavaScript+Unit+Testing" title="Slashdot It!"><img src="http://slashdot.org/favicon.ico" height="16" width="16" alt="[Slashdot]" /></a>
<a href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F&amp;title=JavaScript+Unit+Testing" title="Digg This Story"><img src="http://digg.com/favicon.ico" width="16" height="16" alt="[Digg]" /></a>
<a href="http://reddit.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F&amp;title=JavaScript+Unit+Testing" title="Reddit"><img src="http://reddit.com/favicon.ico" width="16" height="16" alt="[Reddit]" /></a>
<a href="http://del.icio.us/post?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F&amp;title=JavaScript+Unit+Testing" title="Save to del.icio.us" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F&amp;title=JavaScript+Unit+Testing', 'delicious', 'toolbar=no,width=700,height=400'); return false;"><img src="http://images.del.icio.us/static/img/delicious.small.gif" width="16" height="16" alt="[del.icio.us]" /></a>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F" title="Share on Facebook"><img src="http://www.facebook.com/favicon.ico" width="16" height="16" alt="[Facebook]" /></a>
<a href="http://technorati.com/faves?add=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F" title="Add to my Technorati Favorites"><img src="http://technorati.com/favicon.ico" width="16" height="16" alt="[Technorati]" /></a>
<a href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F&amp;title=JavaScript+Unit+Testing" title="Save to Google Bookmarks"><img src="http://www.google.com/favicon.ico" width="16" height="16" alt="[Google]" /></a>
<a href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fajax%2Fjavascript-unit-testing%2F&amp;title=JavaScript+Unit+Testing" title="Stumble it!"><img src="http://www.stumbleupon.com/favicon.ico" width="16" height="16" alt="[StumbleUpon]" /></a>
</span>]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/ajax/javascript-unit-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Headless Javascript Unit Testing</title>
		<link>http://www.reverttoconsole.com/blog/javascript/headless-javascript-unit-testing/</link>
		<comments>http://www.reverttoconsole.com/blog/javascript/headless-javascript-unit-testing/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 13:06:44 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[UnitTest]]></category>

		<guid isPermaLink="false">http://reverttoconsole.com/?p=253</guid>
		<description><![CDATA[I gave a presentation at work a couple of months ago covering JavaScript scoping considerations for a team of Java developers new to JavaScript. During the presentation, I used Rhino to run the examples. I have seen other projects that use Rhino for unit testing, but they seemed a little heavy weight for what I [...]]]></description>
			<content:encoded><![CDATA[<p>I gave a presentation at work a couple of months ago covering JavaScript scoping considerations for a team of Java developers new to JavaScript.</p>
<p>During the presentation, I used <a href="https://developer.mozilla.org/en/Rhino_documentation">Rhino</a> to run the examples. I have <a href="http://httpunit.sourceforge.net/doc/javascript-support.html">seen</a> <a href="http://www.thefrontside.net/crosscheck">other</a> projects that use Rhino for unit testing, but they seemed a little heavy weight for what I wanted to do, which was to write unit tests for the project&#8217;s JavaScript and integrate it into our continuous integration environment.</p>
<p>The following explains what I did instead that seems to work well. I&#8217;d be interested in hearing any alternative suggestions.</p>
<p><span id="more-214"></span></p>
<p>To start with, I used Rhino and <a href="http://code.google.com/p/envjs/">env.js</a> to create a more full featured javascript runtime environment in the jvm, as <a href="http://ejohn.org/projects/bringing-the-browser-to-the-server/">John Resig wrote about a while back</a>. <a href="http://reverttoconsole.com/2008/09/bringing-the-browser-to-the-server-just-discovered-this/">I wrote about this a while back</a>.</p>
<p>Because I wanted to run Rhino and execute JavaScript inside a unit test, it was easiest for me to modify <a href="http://mxr.mozilla.org/mozilla/source/js/rhino/examples/Shell.java">the Shell example provided by the Rhino group</a>.</p>
<p>Note: WordPress was blowing up on me when I tried to show the entire class&#8230; this is the abbreviated version with most of my changes.</p>
<pre>
public class Shell extends ScriptableObject {

    private boolean quitting;
    private static final long serialVersionUID = -5638074146250193112L;
    /**
     * Logger for this class.
     */
    private static final Logger logger = Logger.getLogger(Shell.class);

    @Override
    public String getClassName() {
        return "global";
    }

    public static void print(final Context cx, final Scriptable thisObj, final Object[] args, final Function funObj) {
        for (int i = 0; i < args.length; i++) {
            if (i > 0) {
                logger.info(" ");
            }

            // Convert the arbitrary JavaScript value into a string form.
            String s = Context.toString(args[i]);

            logger.info(s);
        }
    }

    public void quit() {
        quitting = true;
    }

    public static double version(final Context cx, final Scriptable thisObj,
            final Object[] args, final Function funObj) {
        double result = cx.getLanguageVersion();
        if (args.length > 0) {
            double d = Context.toNumber(args[0]);
            cx.setLanguageVersion((int) d);
        }
        return result;

    }

    public static void load(final Context cx, final Scriptable thisObj,
            final Object[] args, final Function funObj) {
        Shell shell = (Shell) getTopLevelScope(thisObj);
        for (int i = 0; i < args.length; i++) {
            shell.processSource(cx, Context.toString(args[i]));
        }
    }

    public static void assertEquals(final String expected, final String actual) {
        Assert.assertEquals(expected, actual);
    }

    public static void assertNotNull(final Object object) {
        Assert.assertTrue(!(object instanceof org.mozilla.javascript.Undefined));
        Assert.assertTrue("Provided object is null", object != null);
    }

    public static void assertTrue(final boolean condition) {
        Assert.assertTrue(condition);
    }

    public static void assertFalse(final boolean condition) {
        Assert.assertFalse(condition);
    }

}
</pre>
<p>Next I created an Abstract JUnit test that loads my Javascript environment. My setUp method looks something like this:</p>
<pre>
    protected void setUp() throws Exception {
        super.setUp();
        context = Context.enter();
        try {

            context.setOptimizationLevel(-1);
            shell = new Shell();
            context.initStandardObjects(shell);

            // Define some global functions particular to the shell. Note
            // that these functions are not part of ECMA.
            String[] names = { "print", "quit", "version", "load",
                    "assertEquals", "assertNotNull",
                    "assertTrue", "assertFalse"};
            shell.defineFunctionProperties(names, Shell.class,
                                           ScriptableObject.DONTENUM);
            shell.processSource(context, "src/test/resources/scripts/startup.js");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
</pre>
<p>This initializes the JavaScript context and loads the environment-specific javascript I want to test. In my case I wanted to test code that uses <a href="http://extjs.com/">ExtJS</a>. My startup.js script looks like this:</p>
<pre>
load('src/test/resources/scripts/env.js');
window.location='src/test/resources/scripts/empty.html';
document='src/test/resources/scripts/empty.html';
load('src/main/javascript/extjs/adapter/ext/ext-base.js');
load('src/main/javascript/extjs/ext-all-debug.js');
load('src/test/resources/scripts/resource.js');
load('src/test/resources/scripts/testdata.js');
load('target/myappcode.js');
</pre>
<p>Order is important here. First, I load env.js. Next I set values for window.location and document. I don't use either explicitly, but some of the other files look for them. Then I load extjs, and my data and app code.</p>
<p>The best part about this arrangement is the predefined functions provided by the shell class. I can easily reference junit assert statements from within my javascript test.</p>
<p>Here is an example JUnit class:</p>
<pre>
public class PhoneNumberTest extends AbstractJSTestCase {

    public PhoneNumberTest(final String name) {
        super(name);
    }

   public void testPhoneCountryCodeRender() {
       processScript("src/test/javascript/PhoneCountryCodeRenderTest.js");
   }

   public void testCreateGrid() {
       processScript("src/test/javascript/PhoneNumberCreateGridTest.js");
   }

}
</pre>
<p>and the javascript test code it calls:</p>
<pre>

var phoneNumber = new edit.form.PhoneNumber();

assertNotNull(phoneNumber);
assertNotNull(profile);

var grid = phoneNumber.createGrid(profile);

assertNotNull(grid);

var store = grid.store;

assertNotNull(store);

assertTrue(store.getCount() === 2);

var record1 = store.getAt(0);
assertNotNull(record1);
var record2 = store.getAt(1);
assertNotNull(record2);

print(record1.data.phoneNumber);
print(record2.data.phoneNumber);

print(record1.data.extension);
print(record2.data.extension);

// Now remove the access code from the phone number
record1.data.phoneNumber = PhoneUtils.removeAccessCode(record1);
print(record1.data.phoneNumber);

record2.data.phoneNumber = PhoneUtils.removeAccessCode(record2);
print(record2.data.phoneNumber);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/javascript/headless-javascript-unit-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running JSLint From Within Eclipse Using Rhino</title>
		<link>http://www.reverttoconsole.com/blog/javascript/running-jslint-from-within-eclipse-using-rhino/</link>
		<comments>http://www.reverttoconsole.com/blog/javascript/running-jslint-from-within-eclipse-using-rhino/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 14:07:15 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://reverttoconsole.com/?p=225</guid>
		<description><![CDATA[Mikko Ohtamaa provides a nice explanation of how to execute JSLint on a javascript file from within eclipse, using Rhino.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.redinnovation.com/2008/03/27/verifying-javascript-files-with-jslint-from-eclipse-ide/">Mikko Ohtamaa</a> provides a nice explanation of how to execute <a href="http://www.jslint.com/">JSLint</a> on a javascript file from within eclipse, using <a href="http://www.mozilla.org/rhino/">Rhino</a>.</p>

<span class="slashdigglicious">
<a href="http://slashdot.org/bookmark.pl?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F&amp;title=Running+JSLint+From+Within+Eclipse+Using+Rhino" title="Slashdot It!"><img src="http://slashdot.org/favicon.ico" height="16" width="16" alt="[Slashdot]" /></a>
<a href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F&amp;title=Running+JSLint+From+Within+Eclipse+Using+Rhino" title="Digg This Story"><img src="http://digg.com/favicon.ico" width="16" height="16" alt="[Digg]" /></a>
<a href="http://reddit.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F&amp;title=Running+JSLint+From+Within+Eclipse+Using+Rhino" title="Reddit"><img src="http://reddit.com/favicon.ico" width="16" height="16" alt="[Reddit]" /></a>
<a href="http://del.icio.us/post?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F&amp;title=Running+JSLint+From+Within+Eclipse+Using+Rhino" title="Save to del.icio.us" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F&amp;title=Running+JSLint+From+Within+Eclipse+Using+Rhino', 'delicious', 'toolbar=no,width=700,height=400'); return false;"><img src="http://images.del.icio.us/static/img/delicious.small.gif" width="16" height="16" alt="[del.icio.us]" /></a>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F" title="Share on Facebook"><img src="http://www.facebook.com/favicon.ico" width="16" height="16" alt="[Facebook]" /></a>
<a href="http://technorati.com/faves?add=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F" title="Add to my Technorati Favorites"><img src="http://technorati.com/favicon.ico" width="16" height="16" alt="[Technorati]" /></a>
<a href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F&amp;title=Running+JSLint+From+Within+Eclipse+Using+Rhino" title="Save to Google Bookmarks"><img src="http://www.google.com/favicon.ico" width="16" height="16" alt="[Google]" /></a>
<a href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Frunning-jslint-from-within-eclipse-using-rhino%2F&amp;title=Running+JSLint+From+Within+Eclipse+Using+Rhino" title="Stumble it!"><img src="http://www.stumbleupon.com/favicon.ico" width="16" height="16" alt="[StumbleUpon]" /></a>
</span>]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/javascript/running-jslint-from-within-eclipse-using-rhino/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dirt Simple EXTJS Grid on Grails</title>
		<link>http://www.reverttoconsole.com/blog/javascript/dirt-simple-extjs-grid-on-grails/</link>
		<comments>http://www.reverttoconsole.com/blog/javascript/dirt-simple-extjs-grid-on-grails/#comments</comments>
		<pubDate>Mon, 25 Aug 2008 14:37:53 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[extjs]]></category>

		<guid isPermaLink="false">http://reverttoconsole.com/?p=223</guid>
		<description><![CDATA[At my current contract, I&#8217;ve been using the popular EXTJS javascript library. In order to get up to speed faster, I&#8217;ve started a small project to assist my learning. I thought about using a number of back ends to support my project, but decided on Grails after reading about the built-in JSON converters. Getting started [...]]]></description>
			<content:encoded><![CDATA[<p>At my current contract, I&#8217;ve been using the popular <a href="http://extjs.com/">EXTJS </a>javascript library. In order to get up to speed faster, I&#8217;ve started a small project to assist my learning.</p>
<p>I thought about using a number of back ends to support my project, but decided on Grails after reading about the built-in JSON converters.</p>
<p><strong>Getting started note</strong>: Since this is a dirt simple example, I copied extjs into the web-app/js directory. <a href="http://jlorenzen.blogspot.com/2008/08/getting-started-with-grails-and-extjs.html">James Lorenzen looks like he has a better way</a>, and there <a href="http://grails.org/Ext+Plugin">might be a plugin some day</a>.</p>
<p>I started with a simple GORM object, Media, which looks like this:</p>
<pre>
class Media {

	static constraints = {
		releaseDate(nullable: true)
	}

	String title
	Date releaseDate
	Date dateCreated
	Date lastUpdated
}
</pre>
<p>Next I added some startup data by adding it to to Bootstrap.groovy class:</p>
<pre>
     	def m = new Media(releaseDate:null, title: 'Test')
     	m.save()
</pre>
<p>And added a controller:</p>
<pre>
import grails.converters.*

class MediaController {

    def view = {

    }

    def list = {
   	def listResult = [ total: Media.count(), items: Media.list(params)]
        render listResult as JSON
    }
}
</pre>
<p>And I now have a Grails back end that will deliver JSON to extjs! Off to the front end!</p>
<p>First I modified my layout, main.gsp, to add the extjs js and css files:</p>
<pre>
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;&lt;g:layoutTitle default=&quot;Grails&quot; /&gt;&lt;/title&gt;

		&lt;link rel=&quot;stylesheet&quot; href=&quot;${createLinkTo(dir:&#039;js&#039;,file:&#039;ext-2.2/resources/css/ext-all.css&#039;)}&quot;&gt;&lt;/link&gt;
		&lt;link rel=&quot;stylesheet&quot; href=&quot;${createLinkTo(dir:&#039;js&#039;,file:&#039;ext-2.2/resources/css/theme-aero.css&#039;)}&quot;&gt;&lt;/link&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;${createLinkTo(dir:&#039;js&#039;,file:&#039;ext-2.2/adapter/ext/ext-base.js&#039;)}&quot;&gt;&lt;/script&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;${createLinkTo(dir:&#039;js&#039;,file:&#039;ext-2.2/ext-all-debug.js&#039;)}&quot;&gt;&lt;/script&gt;
		&lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;
			Ext.BLANK_IMAGE_URL = &quot;${createLinkTo(dir:&#039;js&#039;,file:&#039;ext-2.2/resources/images/default/s.gif&#039;)}&quot;;
		&lt;/script&gt;
		&lt;g:layoutHead /&gt;

	&lt;/head&gt;
	&lt;body&gt;
		&lt;div id=&quot;container&quot;&gt;
			&lt;div id=&quot;content&quot;&gt;
				&lt;div id=&quot;include&quot;&gt;
					&lt;g:layoutBody /&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>and added my view.gsp:</p>
<pre>
&lt;html&gt;
	&lt;head&gt;
		&lt;meta name=&quot;layout&quot; content=&quot;main&quot; /&gt;
		&lt;title&gt;Decorated&lt;/title&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;${createLinkTo(dir:&#039;js&#039;,file:&#039;oscar.js&#039;)}&quot;&gt;&lt;/script&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div id=&quot;center-div&quot;&gt;&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>and lastly, my js file, taken nearly verbatim from an extjs example:</p>
<pre>
/*
 * Ext JS Library 2.0 Beta 1
 * Copyright(c) 2006-2007, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 */

Ext.onReady(function(){

    // create the Data Store
    var ds = new Ext.data.Store({
       autoLoad: true,
       proxy: new Ext.data.HttpProxy({
       url: 'http://localhost:8080/oscar/media/list'}),
       reader: new Ext.data.JsonReader({
       	results: 'total',
       	root:'items',
       	id:'id'
       },
       [
               {name: 'title'},
               {name: 'dateCreated'},
               {name: 'lastUpdated'},
               {name: 'releaseDate'}
          ]
       )
    });

    var cm = new Ext.grid.ColumnModel([
	    {header: "Title", width: 120, dataIndex: 'title'},
		{header: "Created Date", width: 180, dataIndex: 'dateCreated'},
		{header: "Last Updated", width: 115, dataIndex: 'lastUpdated'},
		{header: "releaseDate", width: 100, dataIndex: 'releaseDate'}
	]);
    cm.defaultSortable = true;

    // create the grid
    var grid = new Ext.grid.GridPanel({
        ds: ds,
        cm: cm,
        renderTo:'center-div',
        width:540,
        height:200
    });
});
</pre>
<p><a href="http://svn.reverttoconsole.com/rtc/oscar/">My code is checked in here</a>.</p>

<span class="slashdigglicious">
<a href="http://slashdot.org/bookmark.pl?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F&amp;title=Dirt+Simple+EXTJS+Grid+on+Grails" title="Slashdot It!"><img src="http://slashdot.org/favicon.ico" height="16" width="16" alt="[Slashdot]" /></a>
<a href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F&amp;title=Dirt+Simple+EXTJS+Grid+on+Grails" title="Digg This Story"><img src="http://digg.com/favicon.ico" width="16" height="16" alt="[Digg]" /></a>
<a href="http://reddit.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F&amp;title=Dirt+Simple+EXTJS+Grid+on+Grails" title="Reddit"><img src="http://reddit.com/favicon.ico" width="16" height="16" alt="[Reddit]" /></a>
<a href="http://del.icio.us/post?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F&amp;title=Dirt+Simple+EXTJS+Grid+on+Grails" title="Save to del.icio.us" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F&amp;title=Dirt+Simple+EXTJS+Grid+on+Grails', 'delicious', 'toolbar=no,width=700,height=400'); return false;"><img src="http://images.del.icio.us/static/img/delicious.small.gif" width="16" height="16" alt="[del.icio.us]" /></a>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F" title="Share on Facebook"><img src="http://www.facebook.com/favicon.ico" width="16" height="16" alt="[Facebook]" /></a>
<a href="http://technorati.com/faves?add=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F" title="Add to my Technorati Favorites"><img src="http://technorati.com/favicon.ico" width="16" height="16" alt="[Technorati]" /></a>
<a href="http://www.google.com/bookmarks/mark?op=edit&amp;output=popup&amp;bkmk=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F&amp;title=Dirt+Simple+EXTJS+Grid+on+Grails" title="Save to Google Bookmarks"><img src="http://www.google.com/favicon.ico" width="16" height="16" alt="[Google]" /></a>
<a href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.reverttoconsole.com%2Fblog%2Fjavascript%2Fdirt-simple-extjs-grid-on-grails%2F&amp;title=Dirt+Simple+EXTJS+Grid+on+Grails" title="Stumble it!"><img src="http://www.stumbleupon.com/favicon.ico" width="16" height="16" alt="[StumbleUpon]" /></a>
</span>]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/javascript/dirt-simple-extjs-grid-on-grails/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Generic search for auto complete using Hibernate, Ajax, Scriptaculous &#8211; Part 1</title>
		<link>http://www.reverttoconsole.com/blog/ajax/generic-search-for-auto-completers-using-hibernate-ajax-part-1/</link>
		<comments>http://www.reverttoconsole.com/blog/ajax/generic-search-for-auto-completers-using-hibernate-ajax-part-1/#comments</comments>
		<pubDate>Fri, 13 Apr 2007 10:49:21 +0000</pubDate>
		<dc:creator>Priyatam</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Hibernate/JPA]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://reverttoconsole.com/archives/92</guid>
		<description><![CDATA[Ever wondered how to write a custom search function with pattern matching, generic enough to for an auto completer using Hibernate? In this part I will explain the back end portion of writing an auto completer, for the next part you will see an Ajax front end using DWR and scriptaculous. Use Case Scenario - [...]]]></description>
			<content:encoded><![CDATA[<p>Ever wondered how to write a custom search function with pattern matching, generic enough to for an auto completer using Hibernate? In this part I will explain the back end portion of writing an auto completer, for the next part you will see an Ajax front end using DWR and scriptaculous.</p>
<p><strong>Use Case Scenario </strong>- User has a text input field. User types in &#8220;Bi&#8221; and a request is sent to the server for searching all matching strings with &#8220;Bi&#8221;.</p>
<p><strong>Technical Challenges</strong> Implementing this functionality for a single scenario should be straight forward but having a solution generic enough that any single or a combination of attributes of your domain objects could be searched using hibernate in the dao layer, has some challenges. Also remember, we are not interesting in Pojos but returning &#8220;Hibernate Objects&#8221; to the UI.</p>
<p><strong>Solution</strong> In this example, I use a domain object, <a href="http://gforge.nci.nih.gov/plugins/scmcvs/cvsweb.php/~checkout~/c3prv2/codebase/projects/core/src/edu/duke/cabig/c3pr/domain/ResearchStaff.java?rev=1.2;content-type=text%2Fplain;cvsroot=c3prv2">ResearchStaff</a>. Let&#8217;s say, the first request from the client is matchResearchStaffs(String textPattern). Your Controller (or ajax facade) would look something similar.</p>
<pre>public List<researchStaff> matchResearchStaffs(String text, HttpServletRequest request) throws Exception{
    List <researchStaff> staffCol = researchStaffDao.getBySubnames(extractSubnames(text));

    // The below code is not required for simple searches. But if your ResearchStaff Object has a lot
    // of attributes and collections. You may want to strip it off or "reduce" it before sending it to the UI
    List <researchStaff> reducedStaffCol = new ArrayList <researchStaff>(staffCol.size());
    for (ResearchStaff staff : staffCol) {
        reducedStaffCol.add(buildReduced(staff, Arrays.asList("id", "firstName","lastName")));
    }

     return reducedStaffCol;
}
</pre>
<p>As you see, the controller delegates to Dao for pattern matching and this is where Dao is smart enough to figure out &#8216;which&#8217; domain object&#8217;s &#8216;what&#8217; attributes are being queried. <a href="http://reverttoconsole.com/archives/93">In my last article</a>, you&#8217;ve seen how to couple an abstract domain object to a Base Dao and make it &#8216;aware&#8217;. Well, here you see the real benefits of that coupling.</p>
<p><span id="more-84"></span></p>
<pre>
    /**
     * A query builder for use by subclass DAOs.  It makes it easy to match a fragment of a name
     * or identifier against multiple properties.  This is intended for use in implementing
     * user-friendly dynamic searches; e.g., autocompleters.
     *
     * @param subnames the name fragments to search on
     * @param extraConditions custom HQL conditions with which to constrain the fragment matches
     * @param extraParameters parameters for the custom conditions
     * @param substringMatchProperties a list of properties of the implementing object which should
     *             be matched as case-insensitive substrings
     * @param exactMatchProperties a list of properties which should be matched as case-insensitive
     *             full strings
     * @return a list of matching domain object instances
     */
    @SuppressWarnings("unchecked")
    protected List<t> findBySubname(
        String[] subnames, String extraConditions, List<object> extraParameters,
        List<string> substringMatchProperties, List<string> exactMatchProperties
    ) {
        StringBuilder query = new StringBuilder("from ")
            .append(domainClass().getName()).append(" o where ");
        if (extraConditions != null) query.append(extraConditions).append(" and ");
        List<object> params = new LinkedList<object>();
        if (extraParameters != null) params.addAll(extraParameters);

        for (int i = 0; i < subnames.length; i++) {
            buildSubnameQuery(subnames[i], query, params,
                substringMatchProperties, exactMatchProperties);
            if (i < subnames.length - 1) query.append(" and ");
        }

        log.debug("query string = " +query);
        return getHibernateTemplate().find(query.toString(), params.toArray());
    }

    protected void buildSubnameQuery(
        String subname, StringBuilder query, List<object> params,
        List<string> substringMatchProperties, List<string> exactMatchProperties) {
        query.append('(');
        if (hasAny(substringMatchProperties)) {
            for (Iterator<string> it = substringMatchProperties.iterator(); it.hasNext();) {
                String prop = it.next();
                query.append("LOWER(o.").append(prop).append(") LIKE ?");
                params.add('%' + subname.toLowerCase() + '%');
                if (it.hasNext()) query.append(" or ");
            }
            if (hasAny(exactMatchProperties)) {
                query.append(" or ");
            }
        }
        if (hasAny(exactMatchProperties)) {
            for (Iterator<string> it = exactMatchProperties.iterator(); it.hasNext();) {
                String prop = it.next();
                query.append("LOWER(o.").append(prop).append(") = ?");
                params.add(subname.toLowerCase());
                if (it.hasNext()) query.append(" or ");
            }
        }
        query.append(')');
    }

    private boolean hasAny(List<string> properties) {
        return properties != null &#038;&#038; properties.size() > 0;
    }</pre>
<p>For more working code and complex use cases, feel free to look into our <font face="courier new" size="2"><a href="http://gforge.nci.nih.gov/plugins/scmcvs/cvsweb.php/c3prv2/codebase/projects/?cvsroot=c3prv2">gforge codebase</a></font> in the core/web sub projects</p>
<p><font face="courier new" size="2"><a href="http://gforge.nci.nih.gov/plugins/scmcvs/cvsweb.php/~checkout~/c3prv2/codebase/projects/core/src/edu/duke/cabig/c3pr/dao/AbstractBaseDao.java?rev=1.10;content-type=text%2Fplain;cvsroot=c3prv2">AbstractBaseDao</a><br />
<a href="http://gforge.nci.nih.gov/plugins/scmcvs/cvsweb.php/c3prv2/codebase/projects/web/src/edu/duke/cabig/c3pr/web/ajax/?cvsroot=c3prv2">StudyAjaxFacade</a></font><code></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.reverttoconsole.com/blog/ajax/generic-search-for-auto-completers-using-hibernate-ajax-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

