<?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>mikejuniper.com</title>
	<atom:link href="http://www.mikejuniper.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mikejuniper.com</link>
	<description>Thoughts on GIS software development and life.</description>
	<lastBuildDate>Fri, 09 Dec 2011 20:17:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Diving in to Backbone.js</title>
		<link>http://www.mikejuniper.com/2011/12/diving-in-to-backbone-js/</link>
		<comments>http://www.mikejuniper.com/2011/12/diving-in-to-backbone-js/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 20:12:27 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[Backbone.js]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=192</guid>
		<description><![CDATA[We&#8217;ve known for a while that there are a number of javascript mvc frameworks out there and that many of the apps we build would likely benefit greatly from using one. Bet we&#8217;ve held back mostly because of the learning curve/ time constraints but also partly because it wasn&#8217;t clear which one was gonna be [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve known for a while that there are a number of javascript mvc frameworks out there and that many of the apps we build would likely benefit greatly from using one. Bet we&#8217;ve held back mostly because of the learning curve/ time constraints but also partly because it wasn&#8217;t clear which one was gonna be &#8216;best&#8217; for our needs. Well, we&#8217;ve got a particular project on our plate right now that just begs for a framework like this so we decided to take the plunge. We settled on <a href="http://documentcloud.github.com/backbone/">Backbone.js</a> mostly because it seems like there are lots of super smart people who are using it (and they still like it!) and also because there seem to be lots of resources available for it (not least of which is the very good documentation). </p>
<p>I don&#8217;t really have the time to do a proper Intro to Backbone post but fortunately many others have done so. Some are better than others though, so what I thought I&#8217;d do is share some of the resources I found most helpful and mention a few of the additional libraries we&#8217;re using.</p>
<p>It&#8217;s true that the learning curve is somewhat steep but once you dive in, it&#8217;s not really that bad. A good place to start is <a href="http://backbonetutorials.com/">http://backbonetutorials.com/</a> which provides a brief introduction to the various backbone components. A very easy to understand and quite good hello world example is at <a href="http://arturadib.com/hello-backbonejs/docs/1.html">http://arturadib.com/hello-backbonejs/docs/1.html</a>. This one is cool because it starts very simply and progressively adds complexity.</p>
<p>Rob Conery wrote a <a href="http://wekeroad.com/2011/08/11/the-backbonejs-todo-list-sample-refactored-part-1/">two</a> <a href="http://wekeroad.com/2011/08/12/the-backbone-js-todo-list-refactored-part-2-being/">part</a> post discussing some of the problems he saw with many Backbone tutorials. I was really happy to see this because I shared some of his objections.</p>
<p>One of the things I missed when I first started this project was model binding. Then I found <a href="https://github.com/derickbailey/backbone.modelbinding">this</a> awesome plugin for Backbone which provides two-way, convention-based model binding. This was ridiculously easy to use and it allowed me to slim down my views considerably.</p>
<p>One issue I had was that the particular needs of our app called for messaging between various components other than just a model and its view. For instance, I needed my Results view to know when my Criteria model changed so it could update itself with new data based on the Criteria model that changed; but other than that, the Results view needed no knowledge of the Criteria model. I initially used a shared reference to the Criteria model but I didn&#8217;t love it because I wanted my components to be more loosely coupled. I now think that would have been fine but my dissatisfaction lead me to <a href="http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/">this</a> post that suggests using the Event Aggregator pattern. It&#8217;s really very simple. Since I already had all my modules namespaced, I just put my event aggregator as a property on my namespace object and all my other modules have access to it:</p>
<pre>
dts.eventAggregator = _.extend({}, Backbone.Events);
</pre>
<p>Then you can just do
<pre>dts.eventAggregator.bind('fooEvent', fooEventHandler, this);</pre>
<p> and
<pre>dts.eventAggregator.trigger('fooEvent', {/*event arguments*/});</pre>
<p>I found <a href="http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/">this</a> very good post discussing a good approach to avoiding memory leaks. One of the comments lead me to <a href="http://stackoverflow.com/questions/7567404/backbone-js-repopulate-or-recreate-the-view/7607853#7607853">this</a> StackOverflow post discussing the same issue. I think a combination of these two approaches would work well.</p>
<p>Though I&#8217;m new to javascript mvc frameworks, I&#8217;ve been using javascript templating for a while now. I&#8217;ve mostly been using jQuery Templates which I like just fine, but I took this opportunity to try some other templating engines. I ended up settling on <a href="http://icanhazjs.com/">icanhaz.js</a> because it uses the <a href="http://mustache.github.com/">mustache.js</a> template syntax (it actually uses mustache under the covers, I think) which I like very much and because it precompiles the templates into functions (thus improving performance, I assume) and hangs them right on the ich object with the function name corresponding to the id of the template (thus making it very easy to use). I&#8217;ll definitely be sticking with icanhaz going forward.</p>
<p>Of course, one of the best things about the MVC pattern is that it lends itself quite well to testing. I found a very nice multi-part post on testing backbone applications &#8211; the first part is <a href="http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html">here</a>. I had used <a href="http://docs.jquery.com/QUnit">qUnit</a> before so I decided to stay with it to minimize the risk of my head exploding from all the new stuff (though I was tempted to give <a href="https://github.com/pivotal/jasmine/">Jasmine</a> a whirl). The post above lead me to <a href="http://sinonjs.org/">sinon.js</a> (and its qUnit adapter, <a href="http://sinonjs.org/qunit/">sinon-qunit</a>) which is a really great little library that provides test spies, stubs, and mocks. Unit testing this stuff was fun and it actually helped me uncover some bugs that I didn&#8217;t notice in my ui testing.</p>
<p>I&#8217;ve learned a ton this week, which is always fun, and I&#8217;m looking forward to building more applications with Backbone.js.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/12/diving-in-to-backbone-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Loading a blog feed on your website</title>
		<link>http://www.mikejuniper.com/2011/07/loading-a-blog-feed-on-your-website/</link>
		<comments>http://www.mikejuniper.com/2011/07/loading-a-blog-feed-on-your-website/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 19:14:46 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=187</guid>
		<description><![CDATA[Recently I needed to load recent blog posts onto a website. I discovered the Google Feed API which, as most things Google, is awesome. I also discovered this jQuery plugin which uses it along with what appears to be an old version of their Dynamic Feed Control. This plugin, like all of Mike Alsup&#8217;s other [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I needed to load recent blog posts onto a website. I discovered the <a href="http://code.google.com/apis/feed/v1/">Google Feed API</a> which, as most things Google, is awesome. I also discovered <a href="http://jquery.malsup.com/gfeed/">this</a> jQuery plugin which uses it along with what appears to be an old version of their Dynamic Feed Control. This plugin, like all of Mike Alsup&#8217;s other plugins, is great. However, I couldn&#8217;t get it to work exactly the way I wanted. So I built my own.</p>
<p>I also borrowed and modified some <a href="http://ejohn.org/blog/javascript-pretty-date/">code</a> from John Resig to format the dates. Oh yeah, it also depends on the <a href="http://api.jquery.com/category/plugins/templates/">jQuery Templating Plugin</a>.</p>
<p>It takes an options argument with a required url property and a couple of other optional properties, gets the feed, and loads the items into semantic markup inside the selected element. You can then style it any way you want.</p>
<pre>
/**
*  Plugin which uses the Google AJAX Feed API for creating feed content
*  depends on jquery template plugin
*  very loosely based on http://jquery.malsup.com/gfeed/
*/

(function ($) {
    if (!$.template) {
        alert('You must include the jQuery Templating Plugin script');
        return;
    }

    //feed item template
    var templateHtml = '&lt;div&gt;' +
                            '&lt;div class="feed-item"&gt;' +
                                '&lt;a href="${link}" target="_blank"&gt;' +
                                    '&lt;h2 class="feed-title"&gt;${title}&lt;/h2&gt;' +
                                '&lt;/a&gt;' +
                                '&lt;div class="feed-snippet"&gt;${contentSnippet}&lt;/div&gt;' +
                                '&lt;div class="feed-footer"&gt;Posted ${publishedDate} by ${author}&lt;/div&gt;' +
                            '&lt;/div&gt;' +
                        '&lt;/div&gt;';

    //from based on code from John Resig
    // - http://ejohn.org/blog/javascript-pretty-date/
    function prettyDate(dateString) {
        var date = new Date(dateString);
        diff = (((new Date()).getTime() - date.getTime()) / 1000),
		            day_diff = Math.floor(diff / 86400);

        if (isNaN(day_diff) || day_diff < 0) {
            return;
        }

        return day_diff == 0 &#038;&#038; (
			        diff < 60 &#038;&#038; "just now" ||
			        diff < 120 &#038;&#038; "1 minute ago" ||
			        diff < 3600 &#038;&#038; Math.floor(diff / 60) + " minutes ago" ||
			        diff < 7200 &#038;&#038; "1 hour ago" ||
			        diff < 86400 &#038;&#038; Math.floor(diff / 3600) + " hours ago") ||
		            day_diff == 1 &#038;&#038; "Yesterday" ||
		            day_diff < 7 &#038;&#038; day_diff + " days ago" ||
		            day_diff < 42 &#038;&#038; Math.ceil(day_diff / 7) + " weeks ago" ||
                    day_diff >= 42 &#038;&#038; Math.floor(day_diff / 31) + " months ago";
    }
    new Date().tou
    $.fn.feed = function (options) {
        var opts = $.extend({
            url: '',
            target: this,
            title: 'The latest from our blog',
            max: 5   // max number of items
        }, options || {});

        //show a loading indicator
        opts.target.append('&lt;div id="feed-loading"&gt;loading blog feed...&lt;/div&gt;');

        //get the feed items
        var feedItemTemplate = $(templateHtml).template();
        var gFeedsUrl = 'http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&#038;callback=?&#038;num=' + opts.max + '&#038;q='
        $.ajax({
            url: gFeedsUrl + encodeURIComponent(opts.url),
            dataType: 'json',
            success: function (response) {
                //remove the loading indicator
                $('#feed-loading').remove();

                if (response &#038;&#038; response.responseData
                                  &#038;&#038; response.responseData.feed
                                  &#038;&#038; response.responseData.feed.entries) {
                    var feedItems = response.responseData.feed.entries;
                    //map them to format the date
                    $.map(feedItems, function (item, idx) {
                        item.publishedDate = prettyDate(item.publishedDate);
                        return item;
                    });
                    //load the feeds into the dom
                    opts.target.append('&lt;h1&gt;' + opts.title + '&lt;/h1&gt;&lt;div id="rss-feed"&gt;&lt;/div&gt;')
                        .find('#rss-feed')
                        .append($.tmpl(feedItemTemplate, feedItems));
                } else {
                    opts.target.append('&lt;div id="feed-error"&gt;Unable to retrieve blog feed.&lt;/div&gt;');
                }
            }
        });

        return this;
    };
})(jQuery);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/07/loading-a-blog-feed-on-your-website/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sending javascript dates to Asp.NET</title>
		<link>http://www.mikejuniper.com/2011/07/sending-javascript-dates-to-asp-net/</link>
		<comments>http://www.mikejuniper.com/2011/07/sending-javascript-dates-to-asp-net/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 19:04:04 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=185</guid>
		<description><![CDATA[I&#8217;ve struggled with this at various times and come up with a number of solutions, none of which were entirely satisfying. Now, thanks to Stackoverflow, I found a really nice solution: Javascript: obj.date = new Date().toUTCString(); C#: DateTime date= DateTime.ParseExact(obj.date, "ddd, MMM d yyyy HH:mm:ss GMT", CultureInfo.InvariantCulture);]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve struggled with this at various times and come up with a number of solutions, none of which were entirely satisfying. Now, thanks to <a href="http://stackoverflow.com/questions/6702705/how-to-convert-javascript-datetime-to-c-datetime/6702719#6702719">Stackoverflow</a>, I found a really nice solution:</p>
<p>Javascript:</p>
<pre>
obj.date = new Date().toUTCString();
</pre>
<p>C#:</p>
<pre>
DateTime date= DateTime.ParseExact(obj.date,
                                  "ddd, MMM d yyyy HH:mm:ss GMT",
                                  CultureInfo.InvariantCulture);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/07/sending-javascript-dates-to-asp-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>And now for something completely different&#8230;</title>
		<link>http://www.mikejuniper.com/2011/07/and-now-for-something-completely-different/</link>
		<comments>http://www.mikejuniper.com/2011/07/and-now-for-something-completely-different/#comments</comments>
		<pubDate>Sat, 16 Jul 2011 00:02:04 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=179</guid>
		<description><![CDATA[I&#8217;ve been meaning to post about this for years and am finally getting to it. In January of 2007 we bought our house from Jamestown Builders. When it was about a month out of warranty, we noticed that like some of our neighbors&#8217;, our driveway had begun to spall. I called them to see what [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been meaning to post about this for years and am finally getting to it.</p>
<p>In January of 2007 we bought our house from <a href="http://jamestownhomebuilders.com/">Jamestown Builders</a>.  When it was about a month out of warranty, we noticed that like some of our neighbors&#8217;, our driveway had begun to spall.</p>
<p>I called them to see what they were going to do about it and their response was basically that I shouldn&#8217;t have parked my car on it in the winter. Well, I didn&#8217;t very often, but IT&#8217;S A DRIVEWAY! Can I cook in my kitchen? Can I poop in my bathroom? The rationale is that the freeze/ thaw cycles are exacerbated by the stuff they put on the roads (and then drips off my car) to melt ice and that cracks the driveway. According to my research, while that certainly <em>can</em> happen, it should <em>not</em> happen to properly formulated and installed concrete.</p>
<p>Furthermore, I had a concrete driveway in MINNESOTA that was who knows how many years old when I bought the house and on which I parked my truck every day for the 6 years I lived there. Last time I looked (in 2010) that driveway was fine. By now, The Jamestown driveway is 4 years old and it is quite simply disintegrating. I think it&#8217;s outrageous that I&#8217;m going to have to spend at least $3000 on my driveway when the house is barely 5 years old.</p>
<p><a href="http://www.mikejuniper.com/wp-content/uploads/2011/07/IMAG0362.jpg"><img src="http://www.mikejuniper.com/wp-content/uploads/2011/07/IMAG0362-300x225.jpg" alt="driveway" title="driveway" width="300" height="225" class="alignnone size-medium wp-image-180" /></a></p>
<p>The bottom line is that they clearly had a quality problem with their concrete contractor. They know this perfectly well and if they&#8217;d just say so but say, &#8220;sorry you&#8217;re warranty expired&#8221;, I could accept that. But it rankles that they claim it&#8217;s my fault and that it&#8217;s to be expected for a driveway to disintegrate if you use it for it&#8217;s intended purpose.</p>
<p>So I do not recommend purchasing a house from <a href="http://jamestownhomebuilders.com/">Jamestown Builders</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/07/and-now-for-something-completely-different/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Single finger scrolling in Mobile Safari</title>
		<link>http://www.mikejuniper.com/2011/06/single-finger-scrolling-on-ios/</link>
		<comments>http://www.mikejuniper.com/2011/06/single-finger-scrolling-on-ios/#comments</comments>
		<pubDate>Tue, 21 Jun 2011 20:01:11 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=163</guid>
		<description><![CDATA[We built the BackChannel using the Mobile View Engine I discussed in this post. If you hit the site with a phone we serve a mobile version, but if you hit it with a tablet, we serve the full version, which, of course, we expect to work. For the schedule page, I built a nifty [...]]]></description>
			<content:encoded><![CDATA[<p>We built the <a href="http://uc.dtsagile.com">BackChannel</a> using the Mobile View Engine I discussed in <a href="http://www.mikejuniper.com/2011/03/mobile-device-detection-and-android/">this</a> post. If you hit the site with a phone we serve a mobile version, but if you hit it with a tablet, we serve the full version, which, of course, we expect to work. For the <a href="http://uc.dtsagile.com/agenda">schedule</a> page, I built a nifty full screen multi-pane interface that works perfectly in all desktop browsers I tried and in the Android 3.1 browser on my Xoom. But yesterday <a href="http://blog.davebouwman.com/">Dave</a> pointed out that the bottom left and right panes wouldn&#8217;t scroll on iPad.</p>
<p>After a little digging, I found that Mobile Safari doesn&#8217;t support single finger scrolling on divs. You have to use two fingers. This is actually documented in the <a href="http://support.apple.com/manuals/ipad/">iPad User Guide</a>. Presumably this is because on touch based devices it&#8217;s hard to know if you intend to scroll the whole page or just the div. But, like I said, it works perfectly on my Xoom. Now, if I didn&#8217;t know this, I certainly can&#8217;t expect my users to.</p>
<p>I found that <a href="http://www.flexmls.com/developers/2011/04/13/ipad-and-single-finger-scrolling-in-flexmls/">Nick Larson</a> had created a very simple fix to implement single finger scrolling. I took it and rolled it into a jQuery plugin (my first, actually) using <a href="http://www.malsup.com/jquery/">Mike Alsup&#8217;s</a> <a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern">plugin pattern</a>. There are other solutions out there but mine has the virtue of being very easy to understand and very light (644 bytes minified).</p>
<pre>
/*mjuniper 06/21/2011
    based on code from:

http://www.flexmls.com/developers/2011/04/13/

ipad-and-single-finger-scrolling-in-flexmls/
    and http://www.learningjquery.com/2007/10/a-plugin-development-pattern
*/
//
// create closure
//
(function ($) {
    //
    // plugin definition
    //
    $.fn.mobileScroll = function (options) {
        //only do it for iOS devices
        var userAgent = window.navigator.userAgent.toLowerCase();
        if (userAgent.indexOf('ipad') > -1 ||
                userAgent.indexOf('iphone') > -1) {
            this.bind('touchstart', function (evt) {
                var e = evt.originalEvent;
                startY = e.touches[0].pageY;
                startX = e.touches[0].pageX;
            });

            this.bind('touchmove', function (evt) {
                //need the touches property of the native dom event
                // - jquery exposes originalEvent for that
                var e = evt.originalEvent;
                var touches = e.touches[0];
                //cache $(this)
                var $this = $(this);

                // override the touch event’s normal functionality
                e.preventDefault();

                // y-axis
                var touchMovedY = startY - touches.pageY;
                startY = touches.pageY; // reset startY for the next call
                $this.scrollTop($this.scrollTop() + touchMovedY);

                // x-axis
                var touchMovedX = startX - touches.pageX;
                startX = touches.pageX; // reset startX for the next call
                $this.scrollLeft($this.scrollLeft() + touchMovedX);
            });
        }

        return this;
    };
    //
    // end of closure
    //
})(jQuery);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/06/single-finger-scrolling-on-ios/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ESRI UC BackChannel is live!</title>
		<link>http://www.mikejuniper.com/2011/06/esri-uc-backchannel-is-live/</link>
		<comments>http://www.mikejuniper.com/2011/06/esri-uc-backchannel-is-live/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 21:35:31 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[esri]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=159</guid>
		<description><![CDATA[We&#8217;re still tweaking but the BackChannel app for the 2011 ESRI International User Conference is live! We&#8217;ve had tons of fun building this app; we hope you enjoy it.]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re still tweaking but the <a href="http://uc.dtsagile.com/">BackChannel</a> app for the <a href="www.esri.com/UC">2011 ESRI International User Conference</a> is live! We&#8217;ve had tons of fun building this app; we hope you enjoy it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/06/esri-uc-backchannel-is-live/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Esri UC BackChannel app &#8211; localStorage and jQuery deferred</title>
		<link>http://www.mikejuniper.com/2011/06/esri-uc-backchannel-app-localstorage-and-jquery-deferred/</link>
		<comments>http://www.mikejuniper.com/2011/06/esri-uc-backchannel-app-localstorage-and-jquery-deferred/#comments</comments>
		<pubDate>Fri, 10 Jun 2011 22:12:15 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=154</guid>
		<description><![CDATA[So Dave and I recently put together a BackChannel app for the Esri User Conference next month. For the agenda part of it, we wanted to use localStorage to store the data so that after the initial page load, it would be snappy (the session data is several hundred kilobytes). So I built a little [...]]]></description>
			<content:encoded><![CDATA[<p>So <a href="http://blog.davebouwman.com/">Dave</a> and I recently put together a <a href="http://uc.dtsagile.com/">BackChannel</a> app for the Esri User Conference next month. For the agenda part of it, we wanted to use localStorage to store the data so that after the initial page load, it would be snappy (the session data is several hundred kilobytes). So I built a little repository class that wraps all that up using jQuery deferred. Below is the getUcSessions method. Basically, it checks to see if the sessions are in local storage and, if so, returns them, if not, it requests them with an XHR, returns a deferred, and resolves the deferred when it&#8217;s got them. That way my calling code doesn&#8217;t need to know anything about localstorage or the XHR or anything.</p>
<pre>
getUcSessions: function (sessionsJsonPath) {
       //if we've got it in localStorage, return that
       var data = localStorage.getItem(_sessionKey);
       if (data) {
           console.debug('got sessions from localStorage.');
           _ucSessions =JSON.parse(data);
           return _ucSessions;
       }

       //otherwise, load the json and stuff it into localstorage
       //here we return a promise that will be resolved when we've gotten and processed all the data
       var dfd = new $.Deferred();
       $.getJson(sessionsJsonPath, function (sessions) {
            _ucSessions = sessions;
            console.debug('got sessions via XHR.');

            dfd.resolve(_ucSessions);
       });
       return dfd.promise();
}
</pre>
<p>Then to call it, you just do:</p>
<pre>
$.when(_repo.getUcSessions(args.sessionDataUrl)).then(function (ucSessions) {
    //Do stuff with the sessions...

});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/06/esri-uc-backchannel-app-localstorage-and-jquery-deferred/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Collapse the iPad Keypad in Javascript</title>
		<link>http://www.mikejuniper.com/2011/04/collapse-the-ipad-keypad-in-javascript/</link>
		<comments>http://www.mikejuniper.com/2011/04/collapse-the-ipad-keypad-in-javascript/#comments</comments>
		<pubDate>Tue, 26 Apr 2011 19:29:52 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=143</guid>
		<description><![CDATA[I recently built a web application with a search field which geolocates whatever you typed into that field and zooms you to the results. We were severely constrained on UI space so we went without a search button and we just do the search when the user hits the enter key. This worked fine on [...]]]></description>
			<content:encoded><![CDATA[<p>I recently built a web application with a search field which geolocates whatever you typed into that field and zooms you to the results. We were severely constrained on UI space so we went without a search button and we just do the search when the user hits the enter key.</p>
<p>This worked fine on the iPad except that the keypad didn&#8217;t collapse. Of course, you can&#8217;t directly control the keypad in Javascript but I had a hunch that if I just removed focus from the search field, it would collapse. And it worked! Code (jQuery) below:</p>
<pre>$(this).blur();</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/04/collapse-the-ipad-keypad-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iPad and Motorola Xoom – a tale of two browsers</title>
		<link>http://www.mikejuniper.com/2011/04/ipad-and-motorola-xoom-a-tale-of-two-browsers/</link>
		<comments>http://www.mikejuniper.com/2011/04/ipad-and-motorola-xoom-a-tale-of-two-browsers/#comments</comments>
		<pubDate>Tue, 26 Apr 2011 16:16:04 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[ArcGIS JavaScript API]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=138</guid>
		<description><![CDATA[We recently built a web application (several actually) that we needed to work well on tablets. Since the first Android 3.0 (Honeycomb) tablet, the Motorola Xoom, is now out (and since I have one) we were specifically targeting the iPad and the Xoom. Though they both use Webkit based browsers, I ran into a couple [...]]]></description>
			<content:encoded><![CDATA[<p>We recently built a web application (several actually) that we needed to work well on tablets. Since the first Android 3.0 (Honeycomb) tablet, the Motorola Xoom, is now out (and since I have one) we were specifically targeting the iPad and the Xoom. Though they both use Webkit based browsers, I ran into a couple of interesting differences between the two.</p>
<p>First off, I used -webkit-user-select:none; to prevent selection of various elements in the ui. This worked flawlessly in Mobile Safari on the iPad but Chrome on Android does not seem to respect it at all.</p>
<p>I also ran into a couple of issues using the ArcGIS Javascript API on the Xoom. Since Android doesn&#8217;t support SVG, the JSAPI uses canvas and there are evidently some small problems with their canvas implementation. TextSymbol doesn&#8217;t work and neither do any of the fill styles for simple fill symbol except solid and null. Overall the JSAPI works great on the Xoom, though.</p>
<p>I&#8217;m told that the text symbol issue will probably be fixed in the 2.3 release.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/04/ipad-and-motorola-xoom-a-tale-of-two-browsers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blueprint CSS and the ArcGIS Javascript API</title>
		<link>http://www.mikejuniper.com/2011/04/blueprint-css-and-the-arcgis-javascript-api/</link>
		<comments>http://www.mikejuniper.com/2011/04/blueprint-css-and-the-arcgis-javascript-api/#comments</comments>
		<pubDate>Mon, 25 Apr 2011 19:00:17 +0000</pubDate>
		<dc:creator>mike</dc:creator>
				<category><![CDATA[ArcGIS JavaScript API]]></category>

		<guid isPermaLink="false">http://www.mikejuniper.com/?p=132</guid>
		<description><![CDATA[This is one of those things that I&#8217;m posting so that I can remember it in the future, but maybe it will help somebody else too. Blueprint is a css framework I sometimes use. It&#8217;s easy to understand and use. But I&#8217;ve noticed that it stomps on some ArcGIS Javascript API styles and messes up [...]]]></description>
			<content:encoded><![CDATA[<p>This is one of those things that I&#8217;m posting so that I can remember it in the future, but maybe it will help somebody else too.</p>
<p><a href="http://www.blueprintcss.org/">Blueprint</a> is a css framework I sometimes use. It&#8217;s easy to understand and use. But I&#8217;ve noticed that it stomps on some ArcGIS Javascript API styles and messes up the zoom slider. Also, don&#8217;t forget to assign the appropriate class to the body or some appropriate element so the JSAPI styles get applied!</p>
<p>Specifically, some of the table related styles in Blueprint&#8217;s screen.css file are to blame. Generally, I just get rid of all of them but it you want to get surgical about it, the following are the offending declarations:</p>
<pre>table {margin-bottom:1.4em;width:100%;}</pre>
<p>and</p>
<pre>tbody tr:nth-child(even) td, tbody tr.even td {background:#e5ecf9;}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.mikejuniper.com/2011/04/blueprint-css-and-the-arcgis-javascript-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

