<?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>Ed Spencer &#187; Ed Spencer</title>
	<atom:link href="http://edspencer.net/author/admin/feed" rel="self" type="application/rss+xml" />
	<link>http://edspencer.net</link>
	<description>A Sencha Architect</description>
	<lastBuildDate>Sat, 11 Feb 2012 09:20:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Building a data-driven image carousel with Sencha Touch 2</title>
		<link>http://edspencer.net/2012/02/building-a-data-driven-image-carousel-with-sencha-touch-2.html</link>
		<comments>http://edspencer.net/2012/02/building-a-data-driven-image-carousel-with-sencha-touch-2.html#comments</comments>
		<pubDate>Sat, 11 Feb 2012 09:04:02 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Examples]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[touch]]></category>
		<category><![CDATA[apod]]></category>
		<category><![CDATA[astronomy]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[pretty]]></category>
		<category><![CDATA[sencha touch]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=722</guid>
		<description><![CDATA[<p>This evening I embarked on a little stellar voyage that I&#8217;d like to share with you all. Most people with great taste love astronomy and Sencha Touch 2, so why not combine them in a fun evening&#8217;s web app building?</p>
<p>NASA has been running a small site called <a href="http://apod.nasa.gov/apod/astropix.html">APOD</a> (Astronomy Picture Of the Day) for a long time now, as you can probably tell by the <a href="http://apod.nasa.gov/apod/astropix.html">awesome web design</a> of that page. Despite its 1998-era styling, this site incorporates some pretty stunning images of the universe and is begging for a mobile app interpretation.</p>
<p>We&#8217;re not going to go crazy, in fact this whole thing only took about an hour to create, but hopefully it&#8217;s a useful look at how to put something like this together. In this case, we&#8217;re just going to write a quick app that pulls down the last 20 pictures and shows them in a carousel with an optional title.</p>
<p>Here&#8217;s what it looks like live. You&#8217;ll need a webkit browser (Chrome or Safari) to see this, alternatively load up <a href="http://code.edspencer.net/apod">http://code.edspencer.net/apod</a> on a phone or tablet device:</p>
<p><iframe src="http://code.edspencer.net/apod" width="670" height="500" frameborder="0"></iframe></p>
<p>The full source code for <a href="https://github.com/edspencer/APOD">the app is up on github</a>, and we&#8217;ll go through it bit by bit below.</p>
<h2>The App</h2>
<p>Our app consists of 5 files:</p>
<p><b>index.html</b>, which includes our JavaScript files and a little CSS<br />
<b>app.js</b>, which boots our application up<br />
<b>app/model/Picture.js</b>, which represents a single APOD picture<br />
<b>app/view/Picture.js</b>, which shows a picture on the page<br />
<b>app/store/Pictures.js</b>, which fetches the pictures from the APOD RSS feed</p>
<p>The whole thing is up on github and you can <a href="http://code.edspencer.net/apod">see a live demo at http://code.edspencer.net/apod</a>. To see what it&#8217;s doing tap that link on your phone or tablet, and to really feel it add it to your homescreen to get rid of that browser chrome.</p>
<h2>The Code</h2>
<p>Most of the action happens in app.js, which for your enjoyment is more documentation than code. Here&#8217;s the gist of it:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/*</span></div><div class='line' id='LC2'><span class="cm"> * This app uses a Carousel and a JSON-P proxy so make sure they&#39;re loaded first</span></div><div class='line' id='LC3'><span class="cm"> */</span></div><div class='line' id='LC4'><span class="nx">Ext</span><span class="p">.</span><span class="nx">require</span><span class="p">([</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;Ext.carousel.Carousel&#39;</span><span class="p">,</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;Ext.data.proxy.JsonP&#39;</span></div><div class='line' id='LC7'><span class="p">]);</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="cm">/**</span></div><div class='line' id='LC10'><span class="cm"> * Our app is pretty simple - it just grabs the latest images from NASA&#39;s Astronomy Picture Of the Day </span></div><div class='line' id='LC11'><span class="cm"> * (http://apod.nasa.gov/apod/astropix.html) and displays them in a Carousel. This file drives most of</span></div><div class='line' id='LC12'><span class="cm"> * the application, but there&#39;s also:</span></div><div class='line' id='LC13'><span class="cm"> * </span></div><div class='line' id='LC14'><span class="cm"> * * A Store - app/store/Pictures.js - that fetches the data from the APOD RSS feed</span></div><div class='line' id='LC15'><span class="cm"> * * A Model - app/model/Picture.js - that represents a single image from the feed</span></div><div class='line' id='LC16'><span class="cm"> * * A View - app/view/Picture.js - that displays each image</span></div><div class='line' id='LC17'><span class="cm"> * </span></div><div class='line' id='LC18'><span class="cm"> * Our application&#39;s launch function is called automatically when everything is loaded.</span></div><div class='line' id='LC19'><span class="cm"> */</span></div><div class='line' id='LC20'><span class="nx">Ext</span><span class="p">.</span><span class="nx">application</span><span class="p">({</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;apod&#39;</span><span class="p">,</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">models</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;Picture&#39;</span><span class="p">],</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">stores</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;Pictures&#39;</span><span class="p">],</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">views</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;Picture&#39;</span><span class="p">],</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">launch</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kd">var</span> <span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">,</span> <span class="nx">carousel</span><span class="p">;</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC32'><span class="cm">         * The main carousel that drives our app. We&#39;re just telling it to use the Pictures store and</span></div><div class='line' id='LC33'><span class="cm">         * to update the info bar whenever a new image is swiped to</span></div><div class='line' id='LC34'><span class="cm">         */</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">carousel</span> <span class="o">=</span> <span class="nx">Ext</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="s1">&#39;Ext.Carousel&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">store</span><span class="o">:</span> <span class="s1">&#39;Pictures&#39;</span><span class="p">,</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">direction</span><span class="o">:</span> <span class="s1">&#39;horizontal&#39;</span><span class="p">,</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">listeners</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">activeitemchange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">carousel</span><span class="p">,</span> <span class="nx">item</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">setHtml</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">getPicture</span><span class="p">().</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;title&#39;</span><span class="p">));</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC47'><span class="cm">         * This is just a reusable Component that we pin to the top of the page. This is hidden by default</span></div><div class='line' id='LC48'><span class="cm">         * and appears when the user taps on the screen. The activeitemchange listener above updates the </span></div><div class='line' id='LC49'><span class="cm">         * content of this Component whenever a new image is swiped to</span></div><div class='line' id='LC50'><span class="cm">         */</span></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span> <span class="o">=</span> <span class="nx">Ext</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="s1">&#39;Ext.Component&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">cls</span><span class="o">:</span> <span class="s1">&#39;apod-title&#39;</span><span class="p">,</span></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">top</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span></div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">left</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">right</span><span class="o">:</span> <span class="mi">0</span></div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//add both of our views to the Viewport so they&#39;re rendered and visible</span></div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">carousel</span><span class="p">);</span></div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">info</span><span class="p">);</span></div><div class='line' id='LC61'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC63'><span class="cm">         * The Pictures store (see app/store/Pictures.js) is set to not load automatically, so we load it </span></div><div class='line' id='LC64'><span class="cm">         * manually now. This loads data from the APOD RSS feed and calls our callback function once it&#39;s</span></div><div class='line' id='LC65'><span class="cm">         * loaded.</span></div><div class='line' id='LC66'><span class="cm">         * </span></div><div class='line' id='LC67'><span class="cm">         * All we do here is iterate over all of the data, creating an apodimage Component for each item. </span></div><div class='line' id='LC68'><span class="cm">         * Then we just add those items to the Carousel and set the first item active.</span></div><div class='line' id='LC69'><span class="cm">         */</span></div><div class='line' id='LC70'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">getStore</span><span class="p">(</span><span class="s1">&#39;Pictures&#39;</span><span class="p">).</span><span class="nx">load</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">pictures</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC71'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kd">var</span> <span class="nx">items</span> <span class="o">=</span> <span class="p">[];</span></div><div class='line' id='LC72'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC73'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">pictures</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">picture</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC74'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">picture</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;image&#39;</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC75'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span><span class="p">;</span></div><div class='line' id='LC76'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC77'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC78'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span></div><div class='line' id='LC79'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">xtype</span><span class="o">:</span> <span class="s1">&#39;apodimage&#39;</span><span class="p">,</span></div><div class='line' id='LC80'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">picture</span><span class="o">:</span> <span class="nx">picture</span></div><div class='line' id='LC81'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC82'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC83'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC84'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">carousel</span><span class="p">.</span><span class="nx">setItems</span><span class="p">(</span><span class="nx">items</span><span class="p">);</span></div><div class='line' id='LC85'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">carousel</span><span class="p">.</span><span class="nx">setActiveItem</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span></div><div class='line' id='LC86'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC87'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC88'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC89'><span class="cm">         * The final thing is to add a tap listener that is called whenever the user taps on the screen.</span></div><div class='line' id='LC90'><span class="cm">         * We do a quick check to make sure they&#39;re not tapping on the carousel indicators (tapping on</span></div><div class='line' id='LC91'><span class="cm">         * those indicators moves you between items so we don&#39;t want to override that), then either hide </span></div><div class='line' id='LC92'><span class="cm">         * or show the info Component.</span></div><div class='line' id='LC93'><span class="cm">         * </span></div><div class='line' id='LC94'><span class="cm">         * Note that to hide or show this Component we&#39;re adding or removing the apod-title-visible class.</span></div><div class='line' id='LC95'><span class="cm">         * If you look at index.html you&#39;ll see the CSS rules style the info bar and also cause it to fade</span></div><div class='line' id='LC96'><span class="cm">         * in and out when you tap.</span></div><div class='line' id='LC97'><span class="cm">         */</span></div><div class='line' id='LC98'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;tap&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC99'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">e</span><span class="p">.</span><span class="nx">getTarget</span><span class="p">(</span><span class="s1">&#39;.x-carousel-indicator&#39;</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC100'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="nx">titleVisible</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC101'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">removeCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC102'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span></div><div class='line' id='LC103'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span> <span class="k">else</span> <span class="p">{</span></div><div class='line' id='LC104'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">addCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC105'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span></div><div class='line' id='LC106'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC107'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC108'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC109'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC110'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/106be284198dadd27fad8d90481e1062221c5d2b/APOD-app.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_app.js" style="float:right;margin-right:10px;color:#666">APOD-app.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>This is pretty simple stuff and you can probably just follow the comments to see what&#8217;s going on. Basically though the app.js is responsible for launching our application, creating the Carousel and info Components, and setting up a couple of convenient event listeners.</p>
<p>We also had a few other files:</p>
<h2>Picture Model</h2>
<p>Found in app/model/Picture.js, our model is mostly just a list of fields sent back in the RSS feed. There is one that&#8217;s somewhat more complicated than the rest though &#8211; the &#8216;image&#8217; field. Ideally, the RSS feed would have sent back the url of the image in a separate field and we could just pull it out like any other, but alas it is embedded inside the main content.</p>
<p>To get around this, we just specify a convert function that grabs the content field, finds the first image url inside of it and pulls it out. To make sure it looks good on any device we also pass it through <a href="http://www.sencha.com/learn/how-to-use-src-sencha-io/">Sencha IO src</a>, which resizes the image to fit the screen size of whatever device we happen to be viewing it on:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/**</span></div><div class='line' id='LC2'><span class="cm"> * Simple Model that represents an image from NASA&#39;s Astronomy Picture Of the Day. The only remarkable</span></div><div class='line' id='LC3'><span class="cm"> * thing about this model is the &#39;image&#39; field, which uses a regular expression to pull its value out </span></div><div class='line' id='LC4'><span class="cm"> * of the main content of the RSS feed. Ideally the image url would have been presented in its own field</span></div><div class='line' id='LC5'><span class="cm"> * in the RSS response, but as it wasn&#39;t we had to use this approach to parse it out</span></div><div class='line' id='LC6'><span class="cm"> */</span></div><div class='line' id='LC7'><span class="nx">Ext</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;apod.model.Picture&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">extend</span><span class="o">:</span> <span class="s1">&#39;Ext.data.Model&#39;</span><span class="p">,</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">config</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">fields</span><span class="o">:</span> <span class="p">[</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;link&#39;</span><span class="p">,</span> <span class="s1">&#39;author&#39;</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">,</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;image&#39;</span><span class="p">,</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;string&#39;</span><span class="p">,</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">convert</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">record</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="nx">record</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;content&#39;</span><span class="p">),</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">regex</span>   <span class="o">=</span> <span class="sr">/img src=\&quot;([a-zA-Z0-9\_\.\/\:]*)\&quot;/</span><span class="p">,</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">match</span>   <span class="o">=</span> <span class="nx">content</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">regex</span><span class="p">),</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">src</span>     <span class="o">=</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="nx">src</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">src</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\.gif$/</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">src</span> <span class="o">=</span> <span class="s2">&quot;http://src.sencha.io/screen.width/&quot;</span> <span class="o">+</span> <span class="nx">src</span><span class="p">;</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="nx">src</span><span class="p">;</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">]</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC31'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/96169d323970625b7ac66c51e1a32e5384fdec2e/APOD-model.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_model.js" style="float:right;margin-right:10px;color:#666">APOD-model.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>Pictures Store</h2>
<p>Our Store is even simpler than our Model. All it does is load the APOD RSS feed over JSON-P (via Google&#8217;s <a href="https://developers.google.com/feed/">RSS Feed API</a>) and decode the data with a very simple JSON Reader. This automatically pulls down the images and runs them through our Model&#8217;s convert function:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/**</span></div><div class='line' id='LC2'><span class="cm"> * Grabs the APOD RSS feed from Google&#39;s Feed API, passes the data to our Model to decode</span></div><div class='line' id='LC3'><span class="cm"> */</span></div><div class='line' id='LC4'><span class="nx">Ext</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;apod.store.Pictures&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">extend</span><span class="o">:</span> <span class="s1">&#39;Ext.data.Store&#39;</span><span class="p">,</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">config</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">model</span><span class="o">:</span> <span class="s1">&#39;apod.model.Picture&#39;</span><span class="p">,</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">proxy</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;jsonp&#39;</span><span class="p">,</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&amp;q=http://www.acme.com/jef/apod/rss.xml&amp;num=20&#39;</span><span class="p">,</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">reader</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;json&#39;</span><span class="p">,</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">rootProperty</span><span class="o">:</span> <span class="s1">&#39;responseData.feed.entries&#39;</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC20'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/2356e837605a27fea7ffd31165bc8bc1d6f19b6d/APOD-store.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_store.js" style="float:right;margin-right:10px;color:#666">APOD-store.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>Tying it all together</h2>
<p>Our app.js loads our Model and Store, plus a really simple Picture view that is basically just an <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.Img">Ext.Img</a>. All it does then is render the Carousel and Info Component to the screen and tie up a couple of listeners.</p>
<p>In case you weren&#8217;t paying attention before, the info component is just an Ext.Component that we rendered up in app.js as a place to render the title of the image you&#8217;re currently looking at. When you swipe between items in the carousel the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.carousel.Carousel-event-activeitemchange">activeitemchange event</a> is fired, which we listen to near the top of app.js. All our activeitemchange listener does is update the HTML of the info component to the title of the image we just swiped to.</p>
<p>But what about the info component itself? Well at the bottom of app.js we added a tap listener on Ext.Viewport that hides or shows the info Component whenever you tap anywhere on the screen (except if you tap on the Carousel indicator icons). With a little CSS transition loveliness we get a nice fade in/out transition when we tap the screen to reveal the image title. Here&#8217;s that tap listener again:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/**</span></div><div class='line' id='LC2'><span class="cm"> * The final thing is to add a tap listener that is called whenever the user taps on the screen.</span></div><div class='line' id='LC3'><span class="cm"> * We do a quick check to make sure they&#39;re not tapping on the carousel indicators (tapping on</span></div><div class='line' id='LC4'><span class="cm"> * those indicators moves you between items so we don&#39;t want to override that), then either hide </span></div><div class='line' id='LC5'><span class="cm"> * or show the info Component.</span></div><div class='line' id='LC6'><span class="cm"> */</span></div><div class='line' id='LC7'><span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;tap&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">e</span><span class="p">.</span><span class="nx">getTarget</span><span class="p">(</span><span class="s1">&#39;.x-carousel-indicator&#39;</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="nx">titleVisible</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">removeCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span> <span class="k">else</span> <span class="p">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">addCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC17'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/d07b38cec0f7fb4a1155e9fe30da255df16bafbb/APOD-app-tap-listener.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_app_tap_listener.js" style="float:right;margin-right:10px;color:#666">APOD-app-tap-listener.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>The End of the Beginning</h2>
<p>This was a really simple app that shows how easy it is to put these things together with Sencha Touch 2. Like with most stories though there&#8217;s more to come so keep an eye out for parts 2 and 3 of this intergalactic adventure.</p>
]]></description>
			<content:encoded><![CDATA[<p>This evening I embarked on a little stellar voyage that I&#8217;d like to share with you all. Most people with great taste love astronomy and Sencha Touch 2, so why not combine them in a fun evening&#8217;s web app building?</p>
<p>NASA has been running a small site called <a href="http://apod.nasa.gov/apod/astropix.html">APOD</a> (Astronomy Picture Of the Day) for a long time now, as you can probably tell by the <a href="http://apod.nasa.gov/apod/astropix.html">awesome web design</a> of that page. Despite its 1998-era styling, this site incorporates some pretty stunning images of the universe and is begging for a mobile app interpretation.</p>
<p>We&#8217;re not going to go crazy, in fact this whole thing only took about an hour to create, but hopefully it&#8217;s a useful look at how to put something like this together. In this case, we&#8217;re just going to write a quick app that pulls down the last 20 pictures and shows them in a carousel with an optional title.</p>
<p>Here&#8217;s what it looks like live. You&#8217;ll need a webkit browser (Chrome or Safari) to see this, alternatively load up <a href="http://code.edspencer.net/apod">http://code.edspencer.net/apod</a> on a phone or tablet device:</p>
<p><iframe src="http://code.edspencer.net/apod" width="670" height="500" frameborder="0"></iframe></p>
<p>The full source code for <a href="https://github.com/edspencer/APOD">the app is up on github</a>, and we&#8217;ll go through it bit by bit below.</p>
<h2>The App</h2>
<p>Our app consists of 5 files:</p>
<p><b>index.html</b>, which includes our JavaScript files and a little CSS<br />
<b>app.js</b>, which boots our application up<br />
<b>app/model/Picture.js</b>, which represents a single APOD picture<br />
<b>app/view/Picture.js</b>, which shows a picture on the page<br />
<b>app/store/Pictures.js</b>, which fetches the pictures from the APOD RSS feed</p>
<p>The whole thing is up on github and you can <a href="http://code.edspencer.net/apod">see a live demo at http://code.edspencer.net/apod</a>. To see what it&#8217;s doing tap that link on your phone or tablet, and to really feel it add it to your homescreen to get rid of that browser chrome.</p>
<h2>The Code</h2>
<p>Most of the action happens in app.js, which for your enjoyment is more documentation than code. Here&#8217;s the gist of it:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/*</span></div><div class='line' id='LC2'><span class="cm"> * This app uses a Carousel and a JSON-P proxy so make sure they&#39;re loaded first</span></div><div class='line' id='LC3'><span class="cm"> */</span></div><div class='line' id='LC4'><span class="nx">Ext</span><span class="p">.</span><span class="nx">require</span><span class="p">([</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;Ext.carousel.Carousel&#39;</span><span class="p">,</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;Ext.data.proxy.JsonP&#39;</span></div><div class='line' id='LC7'><span class="p">]);</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="cm">/**</span></div><div class='line' id='LC10'><span class="cm"> * Our app is pretty simple - it just grabs the latest images from NASA&#39;s Astronomy Picture Of the Day </span></div><div class='line' id='LC11'><span class="cm"> * (http://apod.nasa.gov/apod/astropix.html) and displays them in a Carousel. This file drives most of</span></div><div class='line' id='LC12'><span class="cm"> * the application, but there&#39;s also:</span></div><div class='line' id='LC13'><span class="cm"> * </span></div><div class='line' id='LC14'><span class="cm"> * * A Store - app/store/Pictures.js - that fetches the data from the APOD RSS feed</span></div><div class='line' id='LC15'><span class="cm"> * * A Model - app/model/Picture.js - that represents a single image from the feed</span></div><div class='line' id='LC16'><span class="cm"> * * A View - app/view/Picture.js - that displays each image</span></div><div class='line' id='LC17'><span class="cm"> * </span></div><div class='line' id='LC18'><span class="cm"> * Our application&#39;s launch function is called automatically when everything is loaded.</span></div><div class='line' id='LC19'><span class="cm"> */</span></div><div class='line' id='LC20'><span class="nx">Ext</span><span class="p">.</span><span class="nx">application</span><span class="p">({</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;apod&#39;</span><span class="p">,</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">models</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;Picture&#39;</span><span class="p">],</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">stores</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;Pictures&#39;</span><span class="p">],</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">views</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;Picture&#39;</span><span class="p">],</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">launch</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kd">var</span> <span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">,</span> <span class="nx">carousel</span><span class="p">;</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC32'><span class="cm">         * The main carousel that drives our app. We&#39;re just telling it to use the Pictures store and</span></div><div class='line' id='LC33'><span class="cm">         * to update the info bar whenever a new image is swiped to</span></div><div class='line' id='LC34'><span class="cm">         */</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">carousel</span> <span class="o">=</span> <span class="nx">Ext</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="s1">&#39;Ext.Carousel&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">store</span><span class="o">:</span> <span class="s1">&#39;Pictures&#39;</span><span class="p">,</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">direction</span><span class="o">:</span> <span class="s1">&#39;horizontal&#39;</span><span class="p">,</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">listeners</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">activeitemchange</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">carousel</span><span class="p">,</span> <span class="nx">item</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">setHtml</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">getPicture</span><span class="p">().</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;title&#39;</span><span class="p">));</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC47'><span class="cm">         * This is just a reusable Component that we pin to the top of the page. This is hidden by default</span></div><div class='line' id='LC48'><span class="cm">         * and appears when the user taps on the screen. The activeitemchange listener above updates the </span></div><div class='line' id='LC49'><span class="cm">         * content of this Component whenever a new image is swiped to</span></div><div class='line' id='LC50'><span class="cm">         */</span></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span> <span class="o">=</span> <span class="nx">Ext</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="s1">&#39;Ext.Component&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">cls</span><span class="o">:</span> <span class="s1">&#39;apod-title&#39;</span><span class="p">,</span></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">top</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span></div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">left</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">right</span><span class="o">:</span> <span class="mi">0</span></div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//add both of our views to the Viewport so they&#39;re rendered and visible</span></div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">carousel</span><span class="p">);</span></div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">info</span><span class="p">);</span></div><div class='line' id='LC61'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC63'><span class="cm">         * The Pictures store (see app/store/Pictures.js) is set to not load automatically, so we load it </span></div><div class='line' id='LC64'><span class="cm">         * manually now. This loads data from the APOD RSS feed and calls our callback function once it&#39;s</span></div><div class='line' id='LC65'><span class="cm">         * loaded.</span></div><div class='line' id='LC66'><span class="cm">         * </span></div><div class='line' id='LC67'><span class="cm">         * All we do here is iterate over all of the data, creating an apodimage Component for each item. </span></div><div class='line' id='LC68'><span class="cm">         * Then we just add those items to the Carousel and set the first item active.</span></div><div class='line' id='LC69'><span class="cm">         */</span></div><div class='line' id='LC70'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">getStore</span><span class="p">(</span><span class="s1">&#39;Pictures&#39;</span><span class="p">).</span><span class="nx">load</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">pictures</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC71'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kd">var</span> <span class="nx">items</span> <span class="o">=</span> <span class="p">[];</span></div><div class='line' id='LC72'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC73'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">pictures</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">picture</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC74'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">picture</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;image&#39;</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC75'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span><span class="p">;</span></div><div class='line' id='LC76'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC77'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC78'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">items</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span></div><div class='line' id='LC79'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">xtype</span><span class="o">:</span> <span class="s1">&#39;apodimage&#39;</span><span class="p">,</span></div><div class='line' id='LC80'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">picture</span><span class="o">:</span> <span class="nx">picture</span></div><div class='line' id='LC81'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC82'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC83'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC84'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">carousel</span><span class="p">.</span><span class="nx">setItems</span><span class="p">(</span><span class="nx">items</span><span class="p">);</span></div><div class='line' id='LC85'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">carousel</span><span class="p">.</span><span class="nx">setActiveItem</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span></div><div class='line' id='LC86'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC87'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC88'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="cm">/**</span></div><div class='line' id='LC89'><span class="cm">         * The final thing is to add a tap listener that is called whenever the user taps on the screen.</span></div><div class='line' id='LC90'><span class="cm">         * We do a quick check to make sure they&#39;re not tapping on the carousel indicators (tapping on</span></div><div class='line' id='LC91'><span class="cm">         * those indicators moves you between items so we don&#39;t want to override that), then either hide </span></div><div class='line' id='LC92'><span class="cm">         * or show the info Component.</span></div><div class='line' id='LC93'><span class="cm">         * </span></div><div class='line' id='LC94'><span class="cm">         * Note that to hide or show this Component we&#39;re adding or removing the apod-title-visible class.</span></div><div class='line' id='LC95'><span class="cm">         * If you look at index.html you&#39;ll see the CSS rules style the info bar and also cause it to fade</span></div><div class='line' id='LC96'><span class="cm">         * in and out when you tap.</span></div><div class='line' id='LC97'><span class="cm">         */</span></div><div class='line' id='LC98'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;tap&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC99'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">e</span><span class="p">.</span><span class="nx">getTarget</span><span class="p">(</span><span class="s1">&#39;.x-carousel-indicator&#39;</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC100'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="nx">titleVisible</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC101'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">removeCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC102'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span></div><div class='line' id='LC103'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span> <span class="k">else</span> <span class="p">{</span></div><div class='line' id='LC104'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">addCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC105'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span></div><div class='line' id='LC106'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC107'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC108'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">});</span></div><div class='line' id='LC109'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC110'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/106be284198dadd27fad8d90481e1062221c5d2b/APOD-app.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_app.js" style="float:right;margin-right:10px;color:#666">APOD-app.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>This is pretty simple stuff and you can probably just follow the comments to see what&#8217;s going on. Basically though the app.js is responsible for launching our application, creating the Carousel and info Components, and setting up a couple of convenient event listeners.</p>
<p>We also had a few other files:</p>
<h2>Picture Model</h2>
<p>Found in app/model/Picture.js, our model is mostly just a list of fields sent back in the RSS feed. There is one that&#8217;s somewhat more complicated than the rest though &#8211; the &#8216;image&#8217; field. Ideally, the RSS feed would have sent back the url of the image in a separate field and we could just pull it out like any other, but alas it is embedded inside the main content.</p>
<p>To get around this, we just specify a convert function that grabs the content field, finds the first image url inside of it and pulls it out. To make sure it looks good on any device we also pass it through <a href="http://www.sencha.com/learn/how-to-use-src-sencha-io/">Sencha IO src</a>, which resizes the image to fit the screen size of whatever device we happen to be viewing it on:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/**</span></div><div class='line' id='LC2'><span class="cm"> * Simple Model that represents an image from NASA&#39;s Astronomy Picture Of the Day. The only remarkable</span></div><div class='line' id='LC3'><span class="cm"> * thing about this model is the &#39;image&#39; field, which uses a regular expression to pull its value out </span></div><div class='line' id='LC4'><span class="cm"> * of the main content of the RSS feed. Ideally the image url would have been presented in its own field</span></div><div class='line' id='LC5'><span class="cm"> * in the RSS response, but as it wasn&#39;t we had to use this approach to parse it out</span></div><div class='line' id='LC6'><span class="cm"> */</span></div><div class='line' id='LC7'><span class="nx">Ext</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;apod.model.Picture&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">extend</span><span class="o">:</span> <span class="s1">&#39;Ext.data.Model&#39;</span><span class="p">,</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">config</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">fields</span><span class="o">:</span> <span class="p">[</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span><span class="p">,</span> <span class="s1">&#39;link&#39;</span><span class="p">,</span> <span class="s1">&#39;author&#39;</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">,</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;image&#39;</span><span class="p">,</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;string&#39;</span><span class="p">,</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">convert</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">record</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="nx">record</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;content&#39;</span><span class="p">),</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">regex</span>   <span class="o">=</span> <span class="sr">/img src=\&quot;([a-zA-Z0-9\_\.\/\:]*)\&quot;/</span><span class="p">,</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">match</span>   <span class="o">=</span> <span class="nx">content</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">regex</span><span class="p">),</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">src</span>     <span class="o">=</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="nx">src</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">src</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\.gif$/</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">src</span> <span class="o">=</span> <span class="s2">&quot;http://src.sencha.io/screen.width/&quot;</span> <span class="o">+</span> <span class="nx">src</span><span class="p">;</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="nx">src</span><span class="p">;</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">]</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC31'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/96169d323970625b7ac66c51e1a32e5384fdec2e/APOD-model.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_model.js" style="float:right;margin-right:10px;color:#666">APOD-model.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>Pictures Store</h2>
<p>Our Store is even simpler than our Model. All it does is load the APOD RSS feed over JSON-P (via Google&#8217;s <a href="https://developers.google.com/feed/">RSS Feed API</a>) and decode the data with a very simple JSON Reader. This automatically pulls down the images and runs them through our Model&#8217;s convert function:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/**</span></div><div class='line' id='LC2'><span class="cm"> * Grabs the APOD RSS feed from Google&#39;s Feed API, passes the data to our Model to decode</span></div><div class='line' id='LC3'><span class="cm"> */</span></div><div class='line' id='LC4'><span class="nx">Ext</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;apod.store.Pictures&#39;</span><span class="p">,</span> <span class="p">{</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">extend</span><span class="o">:</span> <span class="s1">&#39;Ext.data.Store&#39;</span><span class="p">,</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">config</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">model</span><span class="o">:</span> <span class="s1">&#39;apod.model.Picture&#39;</span><span class="p">,</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">proxy</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;jsonp&#39;</span><span class="p">,</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&amp;q=http://www.acme.com/jef/apod/rss.xml&amp;num=20&#39;</span><span class="p">,</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">reader</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;json&#39;</span><span class="p">,</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">rootProperty</span><span class="o">:</span> <span class="s1">&#39;responseData.feed.entries&#39;</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC20'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/2356e837605a27fea7ffd31165bc8bc1d6f19b6d/APOD-store.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_store.js" style="float:right;margin-right:10px;color:#666">APOD-store.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>Tying it all together</h2>
<p>Our app.js loads our Model and Store, plus a really simple Picture view that is basically just an <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.Img">Ext.Img</a>. All it does then is render the Carousel and Info Component to the screen and tie up a couple of listeners.</p>
<p>In case you weren&#8217;t paying attention before, the info component is just an Ext.Component that we rendered up in app.js as a place to render the title of the image you&#8217;re currently looking at. When you swipe between items in the carousel the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.carousel.Carousel-event-activeitemchange">activeitemchange event</a> is fired, which we listen to near the top of app.js. All our activeitemchange listener does is update the HTML of the info component to the title of the image we just swiped to.</p>
<p>But what about the info component itself? Well at the bottom of app.js we added a tap listener on Ext.Viewport that hides or shows the info Component whenever you tap anywhere on the screen (except if you tap on the Carousel indicator icons). With a little CSS transition loveliness we get a nice fade in/out transition when we tap the screen to reveal the image title. Here&#8217;s that tap listener again:</p>
<div id="gist-1797867" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/**</span></div><div class='line' id='LC2'><span class="cm"> * The final thing is to add a tap listener that is called whenever the user taps on the screen.</span></div><div class='line' id='LC3'><span class="cm"> * We do a quick check to make sure they&#39;re not tapping on the carousel indicators (tapping on</span></div><div class='line' id='LC4'><span class="cm"> * those indicators moves you between items so we don&#39;t want to override that), then either hide </span></div><div class='line' id='LC5'><span class="cm"> * or show the info Component.</span></div><div class='line' id='LC6'><span class="cm"> */</span></div><div class='line' id='LC7'><span class="nx">Ext</span><span class="p">.</span><span class="nx">Viewport</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;tap&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">e</span><span class="p">.</span><span class="nx">getTarget</span><span class="p">(</span><span class="s1">&#39;.x-carousel-indicator&#39;</span><span class="p">))</span> <span class="p">{</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="nx">titleVisible</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">removeCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span> <span class="k">else</span> <span class="p">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">info</span><span class="p">.</span><span class="nx">element</span><span class="p">.</span><span class="nx">addCls</span><span class="p">(</span><span class="s1">&#39;apod-title-visible&#39;</span><span class="p">);</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">titleVisible</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC17'><span class="p">});</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1797867/d07b38cec0f7fb4a1155e9fe30da255df16bafbb/APOD-app-tap-listener.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1797867#file_apod_app_tap_listener.js" style="float:right;margin-right:10px;color:#666">APOD-app-tap-listener.js</a>
            <a href="https://gist.github.com/1797867">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>The End of the Beginning</h2>
<p>This was a really simple app that shows how easy it is to put these things together with Sencha Touch 2. Like with most stories though there&#8217;s more to come so keep an eye out for parts 2 and 3 of this intergalactic adventure.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2012/02/building-a-data-driven-image-carousel-with-sencha-touch-2.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Like Android? Help us fix it</title>
		<link>http://edspencer.net/2012/02/like-android-help-us-fix-it.html</link>
		<comments>http://edspencer.net/2012/02/like-android-help-us-fix-it.html#comments</comments>
		<pubDate>Mon, 06 Feb 2012 18:52:03 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[touch]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[android 4]]></category>
		<category><![CDATA[sencha touch]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=715</guid>
		<description><![CDATA[<p>Near the end of last week&#8217;s <a href="http://www.sencha.com/blog/sencha-touch-2-raising-the-bar">Sencha Touch 2 beta release blog post</a> there was an appeal to the community to help raise awareness of a nasty flashing issue with Android 4.x phones. Every time you tried to use an animation on a web page the browser would flash, wait a bit, then finally perform the animation.</p>
<p>We filed a <a href="http://code.google.com/p/android/issues/detail?id=24833">ticket</a> on this about a week ago and thanks to your help (over 300 of you starred the issue), got a prompt response from the Android team with a fix for the flashing issue.</p>
<h2>Getting it Right</h2>
<p>However, that&#8217;s only half the story. While the ugly flash is gone, animation performance on Android 4.x phones is still unacceptable. As it stands a 2 year old device running Android 2.x easily outruns the top of the range devices today running 4.x.</p>
<p>We really want to have excellent support for all Android devices. While 4.x accounts for only <a href="http://developer.android.com/resources/dashboard/platform-versions.html">1% of all Android phones today</a>, that number is only going to go up. And when it does, we want to be ready to ship fast, fluid, beautiful apps onto it.</p>
<p>So we&#8217;ve created <a href="http://code.google.com/p/android/issues/detail?id=25147">a new ticket with reduced, reproducible test cases and filed it to the bug tracker</a>. We&#8217;ll continue to give the Android team as much support as we can in order to resolve this quickly, but once again we&#8217;ll need your help.</p>
<p><u>In fact all we need is a few seconds of your time</u>. Just <a href="http://code.google.com/p/android/issues/detail?id=25147">open the ticket</a> and click the star at the top left. That&#8217;s all we need &#8211; it tells the Android team just how many people care about this issue and will help them prioritize it accordingly.</p>
<p>If you want to help out more, take a moment to add a comment to the ticket outlining your own experiences with this issue, like the <a href="http://code.google.com/p/android/issues/detail?id=25147#c1">m.lanyrd.com developer</a> did. Highlighting specific cases where you&#8217;ve had problems will really help.</p>
<h2>Thanks!</h2>
<p>Helping raise awareness of this issue will help everyone who uses or develops for Android devices on the web, and enables technologies like Sencha Touch to deliver slick, immersive apps without resorting to rewriting your app for each platform. We appreciate your help!</p>
<p><a href="http://code.google.com/p/android/issues/detail?id=25147">Star the issue now</a></p>
]]></description>
			<content:encoded><![CDATA[<p>Near the end of last week&#8217;s <a href="http://www.sencha.com/blog/sencha-touch-2-raising-the-bar">Sencha Touch 2 beta release blog post</a> there was an appeal to the community to help raise awareness of a nasty flashing issue with Android 4.x phones. Every time you tried to use an animation on a web page the browser would flash, wait a bit, then finally perform the animation.</p>
<p>We filed a <a href="http://code.google.com/p/android/issues/detail?id=24833">ticket</a> on this about a week ago and thanks to your help (over 300 of you starred the issue), got a prompt response from the Android team with a fix for the flashing issue.</p>
<h2>Getting it Right</h2>
<p>However, that&#8217;s only half the story. While the ugly flash is gone, animation performance on Android 4.x phones is still unacceptable. As it stands a 2 year old device running Android 2.x easily outruns the top of the range devices today running 4.x.</p>
<p>We really want to have excellent support for all Android devices. While 4.x accounts for only <a href="http://developer.android.com/resources/dashboard/platform-versions.html">1% of all Android phones today</a>, that number is only going to go up. And when it does, we want to be ready to ship fast, fluid, beautiful apps onto it.</p>
<p>So we&#8217;ve created <a href="http://code.google.com/p/android/issues/detail?id=25147">a new ticket with reduced, reproducible test cases and filed it to the bug tracker</a>. We&#8217;ll continue to give the Android team as much support as we can in order to resolve this quickly, but once again we&#8217;ll need your help.</p>
<p><u>In fact all we need is a few seconds of your time</u>. Just <a href="http://code.google.com/p/android/issues/detail?id=25147">open the ticket</a> and click the star at the top left. That&#8217;s all we need &#8211; it tells the Android team just how many people care about this issue and will help them prioritize it accordingly.</p>
<p>If you want to help out more, take a moment to add a comment to the ticket outlining your own experiences with this issue, like the <a href="http://code.google.com/p/android/issues/detail?id=25147#c1">m.lanyrd.com developer</a> did. Highlighting specific cases where you&#8217;ve had problems will really help.</p>
<h2>Thanks!</h2>
<p>Helping raise awareness of this issue will help everyone who uses or develops for Android devices on the web, and enables technologies like Sencha Touch to deliver slick, immersive apps without resorting to rewriting your app for each platform. We appreciate your help!</p>
<p><a href="http://code.google.com/p/android/issues/detail?id=25147">Star the issue now</a></p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2012/02/like-android-help-us-fix-it.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Sencha Touch 2 Hits Beta</title>
		<link>http://edspencer.net/2012/02/sencha-touch-2-hits-beta.html</link>
		<comments>http://edspencer.net/2012/02/sencha-touch-2-hits-beta.html#comments</comments>
		<pubDate>Wed, 01 Feb 2012 21:46:01 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[touch]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[sencha]]></category>
		<category><![CDATA[sencha touch]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=687</guid>
		<description><![CDATA[<p>Earlier today we released Sencha Touch 2 Beta 1 &#8211; check out the <a href="http://www.sencha.com/blog/sencha-touch-2-raising-the-bar">official sencha.com blog post</a> and <a href="http://dev.sencha.com/deploy/sencha-touch-2-b1/release-notes.html">release notes</a> to find out all of the awesome stuff packed into this release.</p>
<p>This is a really important release for us &#8211; Sencha Touch 2 is another huge leap forward for the mobile web and hitting beta is a massive milestone for everyone involved with the project. From a personal standpoint, working on this release with the amazing Touch team has been immensely gratifying and I hope the end result more than meets your expectations of what the mobile web can do.</p>
<p>While you should check out the official <a href="http://www.sencha.com/blog/sencha-touch-2-raising-the-bar">blog post</a> and release notes to find out the large scale changes, there are a number of things I&#8217;d really like to highlight today.</p>
<h2>A Note on Builds</h2>
<p>Before we get into the meat of B1 itself, first a quick note that we&#8217;ve updated the set of builds that we generate with the release. Previously there had been some confusion around which build you should be using in which circumstances so we&#8217;ve tried to simplify that.</p>
<p>Most people, most of the time should be using the new <i>sencha-touch-debug.js</i> while developing their app as it is unminified code that contains all of the debug warnings and comments. If you&#8217;re migrating from 1.x, use the new builds/sencha-touch-all-compat.js build as it provides an easier migration path by logging additional warnings when you use 1.x-style class configurations.</p>
<p>Because we provide 5 builds in total we created <a href="http://docs.sencha.com/touch/2-0/#!/guide/building">a guide on the shipped builds and JSBuilder</a> (the tool that creates a custom build specifically for your app). The guide contains a table showing all of the options enabled for each build &#8211; hopefully that makes it easy to choose which build is best for your needs.</p>
<h2>Performance</h2>
<p>In case you haven&#8217;t seen Sencha Touch 2 yet the first thing you need to know is that it&#8217;s fast. Crazy fast. Check out this side by side comparison between 1.x and 2.x:</p>
<p><a href="http://vimeo.com/30296006"><img src="http://img1.sencha.com/files/misc/20111010-video-full.jpg" /></a></p>
<p>Layout performance is enormously faster in 2.x due to a brand new layout engine that operates much closer to the browser&#8217;s optimized CSS layout engine. The difference is pretty startling, especially on Android devices, which had sometimes struggled with Sencha Touch 1. Performance remains a top priority for us and we&#8217;re really pleased with the improvements that we&#8217;ve secured with 2.0.</p>
<h2>Navigation View</h2>
<p>The new Navigation View is one of the slickest, sexiest things we&#8217;ve created for 2.0. I could play with this thing all day. If you&#8217;ve got a phone in your pocket or a tablet near by open up <a href="http://dev.sencha.com/deploy/sencha-touch-2-b1/examples/navigationview/">the Navigation View example</a> and see it for yourself. If you&#8217;re not, check out this beautiful video of it in action:</p>
<p> <figure class="aligncenter" style="align: center; margin-left: 135px;"><br />
  <iframe src="http://player.vimeo.com/video/36004489?title=0&amp;byline=0&amp;portrait=0&amp;color=4CC208" width="400" height="570" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br />
 </figure></p>
<p>Navigation Views are really easy to put together and make your application immediately come to life. Check out the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.navigation.View">Navigation View docs</a> to see how easy it is to add this to your own applications.</p>
<h2>Awesome new examples</h2>
<p>As of beta 1 we have 24 examples shipped with the SDK, including no fewer than 6 MVC examples &#8211; Kitchen Sink, Jogs with Friends, Twitter, Kiva, Navigation View and GeoCongress.</p>
<p>The Kitchen Sink and Twitter examples also take advantage of Device Profiles, which are a powerful way to customize your app to render customized UI for tablets and phones. Take a look at the Kitchen Sink on your phone and on an iPad to see how it rearranges itself depending on the screen size.</p>
<p>Finally, if you&#8217;re seeing Sencha Touch 2 for the first time you may not have seen the new inline examples in the documentation center. This is a brand new thing for Sencha Touch and allows you to edit code live on the documentation page and immediately see the results &#8211; give it a go on the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.carousel.Carousel">Carousel docs</a>.</p>
<h2>Ludicrous Amounts of Documentation</h2>
<p>Speaking of docs, we have a stunning amount of learning material for Sencha Touch 2. We&#8217;ve been through all of the major classes, making sure that the functions are clearly documented and that each one has some great intro text that describes what the class does and how it fits in with the rest of the framework.</p>
<p>We&#8217;ve also created <a href="http://docs.sencha.com/touch/2-0/#!/guide">over 20 brand new guides</a> for Sencha Touch 2, covering everything from getting started through to developing using MVC, using Components and creating custom builds for your applications. We&#8217;ve put a huge amount of effort into our docs for Sencha Touch 2 and I really hope it pays off for you guys and makes it easier than ever to create great mobile web apps.</p>
<h2>Go Build Something</h2>
<p>It&#8217;s only beta 1 but we&#8217;re very happy with the performance, stability, API and documentation of Sencha Touch 2. I think it&#8217;s the best thing we&#8217;ve ever created, and really highlights what the mobile web is capable of. 2012 looks set to be a very exciting year for Sencha Touch so I hope you&#8217;ll join us on the adventure and build something amazing with it.</p>
<p><a href="http://cdn.sencha.io/touch/sencha-touch-2-b1.zip">Download Sencha Touch 2 Beta 1 Now</a></p>
]]></description>
			<content:encoded><![CDATA[<p>Earlier today we released Sencha Touch 2 Beta 1 &#8211; check out the <a href="http://www.sencha.com/blog/sencha-touch-2-raising-the-bar">official sencha.com blog post</a> and <a href="http://dev.sencha.com/deploy/sencha-touch-2-b1/release-notes.html">release notes</a> to find out all of the awesome stuff packed into this release.</p>
<p>This is a really important release for us &#8211; Sencha Touch 2 is another huge leap forward for the mobile web and hitting beta is a massive milestone for everyone involved with the project. From a personal standpoint, working on this release with the amazing Touch team has been immensely gratifying and I hope the end result more than meets your expectations of what the mobile web can do.</p>
<p>While you should check out the official <a href="http://www.sencha.com/blog/sencha-touch-2-raising-the-bar">blog post</a> and release notes to find out the large scale changes, there are a number of things I&#8217;d really like to highlight today.</p>
<h2>A Note on Builds</h2>
<p>Before we get into the meat of B1 itself, first a quick note that we&#8217;ve updated the set of builds that we generate with the release. Previously there had been some confusion around which build you should be using in which circumstances so we&#8217;ve tried to simplify that.</p>
<p>Most people, most of the time should be using the new <i>sencha-touch-debug.js</i> while developing their app as it is unminified code that contains all of the debug warnings and comments. If you&#8217;re migrating from 1.x, use the new builds/sencha-touch-all-compat.js build as it provides an easier migration path by logging additional warnings when you use 1.x-style class configurations.</p>
<p>Because we provide 5 builds in total we created <a href="http://docs.sencha.com/touch/2-0/#!/guide/building">a guide on the shipped builds and JSBuilder</a> (the tool that creates a custom build specifically for your app). The guide contains a table showing all of the options enabled for each build &#8211; hopefully that makes it easy to choose which build is best for your needs.</p>
<h2>Performance</h2>
<p>In case you haven&#8217;t seen Sencha Touch 2 yet the first thing you need to know is that it&#8217;s fast. Crazy fast. Check out this side by side comparison between 1.x and 2.x:</p>
<p><a href="http://vimeo.com/30296006"><img src="http://img1.sencha.com/files/misc/20111010-video-full.jpg" /></a></p>
<p>Layout performance is enormously faster in 2.x due to a brand new layout engine that operates much closer to the browser&#8217;s optimized CSS layout engine. The difference is pretty startling, especially on Android devices, which had sometimes struggled with Sencha Touch 1. Performance remains a top priority for us and we&#8217;re really pleased with the improvements that we&#8217;ve secured with 2.0.</p>
<h2>Navigation View</h2>
<p>The new Navigation View is one of the slickest, sexiest things we&#8217;ve created for 2.0. I could play with this thing all day. If you&#8217;ve got a phone in your pocket or a tablet near by open up <a href="http://dev.sencha.com/deploy/sencha-touch-2-b1/examples/navigationview/">the Navigation View example</a> and see it for yourself. If you&#8217;re not, check out this beautiful video of it in action:</p>
<p> <figure class="aligncenter" style="align: center; margin-left: 135px;"><br />
  <iframe src="http://player.vimeo.com/video/36004489?title=0&amp;byline=0&amp;portrait=0&amp;color=4CC208" width="400" height="570" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br />
 </figure></p>
<p>Navigation Views are really easy to put together and make your application immediately come to life. Check out the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.navigation.View">Navigation View docs</a> to see how easy it is to add this to your own applications.</p>
<h2>Awesome new examples</h2>
<p>As of beta 1 we have 24 examples shipped with the SDK, including no fewer than 6 MVC examples &#8211; Kitchen Sink, Jogs with Friends, Twitter, Kiva, Navigation View and GeoCongress.</p>
<p>The Kitchen Sink and Twitter examples also take advantage of Device Profiles, which are a powerful way to customize your app to render customized UI for tablets and phones. Take a look at the Kitchen Sink on your phone and on an iPad to see how it rearranges itself depending on the screen size.</p>
<p>Finally, if you&#8217;re seeing Sencha Touch 2 for the first time you may not have seen the new inline examples in the documentation center. This is a brand new thing for Sencha Touch and allows you to edit code live on the documentation page and immediately see the results &#8211; give it a go on the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.carousel.Carousel">Carousel docs</a>.</p>
<h2>Ludicrous Amounts of Documentation</h2>
<p>Speaking of docs, we have a stunning amount of learning material for Sencha Touch 2. We&#8217;ve been through all of the major classes, making sure that the functions are clearly documented and that each one has some great intro text that describes what the class does and how it fits in with the rest of the framework.</p>
<p>We&#8217;ve also created <a href="http://docs.sencha.com/touch/2-0/#!/guide">over 20 brand new guides</a> for Sencha Touch 2, covering everything from getting started through to developing using MVC, using Components and creating custom builds for your applications. We&#8217;ve put a huge amount of effort into our docs for Sencha Touch 2 and I really hope it pays off for you guys and makes it easier than ever to create great mobile web apps.</p>
<h2>Go Build Something</h2>
<p>It&#8217;s only beta 1 but we&#8217;re very happy with the performance, stability, API and documentation of Sencha Touch 2. I think it&#8217;s the best thing we&#8217;ve ever created, and really highlights what the mobile web is capable of. 2012 looks set to be a very exciting year for Sencha Touch so I hope you&#8217;ll join us on the adventure and build something amazing with it.</p>
<p><a href="http://cdn.sencha.io/touch/sencha-touch-2-b1.zip">Download Sencha Touch 2 Beta 1 Now</a></p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2012/02/sencha-touch-2-hits-beta.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Class System in Sencha Touch 2 &#8211; What you need to know</title>
		<link>http://edspencer.net/2012/01/the-class-system-in-sencha-touch-2-what-you-need-to-know.html</link>
		<comments>http://edspencer.net/2012/01/the-class-system-in-sencha-touch-2-what-you-need-to-know.html#comments</comments>
		<pubDate>Sat, 28 Jan 2012 08:53:05 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[touch]]></category>
		<category><![CDATA[sencha]]></category>
		<category><![CDATA[sencha touch]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=676</guid>
		<description><![CDATA[<p>Sencha Touch 1 used the class system from Ext JS 3, which provides a simple but powerful inheritance system that makes it easier to write big complex things like applications and frameworks.</p>
<p>With Sencha Touch 2 we&#8217;ve taken Ext JS 4&#8217;s much more advanced class system and used it to create a leaner, cleaner and more beautiful framework. This post takes you through what has changed and how to use it to improve your apps.</p>
<h2>Syntax</h2>
<p>The first thing you&#8217;ll notice when comparing code from 1.x and 2.x is that the class syntax is different. Back in 1.x we would define a class like this:</p>
<pre class="brush: jscript;">
MyApp.CustomPanel = Ext.extend(Ext.Panel, {
    html: 'Some html'
});
</pre>
<p>This would create a subclass of Ext.Panel called MyApp.CustomPanel, setting the html configuration to &#8216;Some html&#8217;. Any time we create a new instance of our subclass (by calling new MyApp.CustomPanel()), we&#8217;ll now get a slightly customized Ext.Panel instance.</p>
<p>Now let&#8217;s see how the same class is defined in Sencha Touch 2:</p>
<pre class="brush: jscript;">
Ext.define('MyApp.CustomPanel', {
    extend: 'Ext.Panel',

    config: {
        html: 'Some html'
    }
});
</pre>
<p>There are a few changes here, let&#8217;s go through them one by one. Firstly and most obviously we&#8217;ve swapped out Ext.extend for Ext.define. Ext.define operates using strings &#8211; notice that both &#8216;MyApp.CustomPanel&#8217; and &#8216;Ext.Panel&#8217; are now wrapped in quotes. This enables one of the most powerful parts of the new class system &#8211; dynamic loading.</p>
<p>I actually talked about this in a post about Ext JS 4 last year so if you&#8217;re not familiar you should <a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">check out the post</a>, but in a nutshell Sencha Touch 2 will automatically ensure that the class you&#8217;re extending (Ext.Panel) is loaded on the page, fetching it from your server if necessary. This makes development easier and enables you to create custom builds that only contain the class your app actually uses.</p>
<p>The second notable change is that we&#8217;re using a &#8216;config&#8217; block now. Configs are a special thing in Sencha Touch 2 &#8211; they are properties of a class that can be retrieved and updated at any time, and provide extremely useful hook functions that enable you to run any custom logic you like whenever one of them is changed.</p>
<p>Whenever you want to customize any of the configurations of a subclass in Sencha Touch 2, just place them in the config block and the framework takes care of the rest, as we&#8217;ll see in a moment.</p>
<h2>Consistency</h2>
<p>The biggest improvement that comes from the config system is consistency. Let&#8217;s take our MyApp.CustomPanel class above and create an instance of it:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel');
</pre>
<p>Every configuration has an automatically generated getter and setter function, which we can use like this:</p>
<pre class="brush: jscript;">
myPanel.setHtml('New HTML');
myPanel.getHtml(); //returns 'New HTML'
</pre>
<p>This might not seem much, but the convention applies to every single configuration in the entire framework. This eliminates the guesswork from the API &#8211; if you know the config name, you know how to get it and update it. Contrast this with Sencha Touch 1 where retrieving the html config meant finding some property on the instance, and updating it meant calling myPanel.update(&#8217;New HTML&#8217;), which is nowhere near as predictable.</p>
<h2>Instantiating</h2>
<p>You probably noticed that we used a new function above &#8211; Ext.create. This is very similar to just calling &#8216;new MyApp.CustomPanel()&#8217;, with the exception that Ext.create uses the dynamic loading system to automatically load the class you are trying to instantiate if it is not already on the page. This can make life much easier when developing your app as you don&#8217;t have to immediately manage dependencies &#8211; it just works.</p>
<p>In the example above we just instantiated a default MyApp.CustomPanel but of course we can customize it at instantiation time by passing configs into Ext.create:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel', {
    html: 'Some Custom HTML'
});
</pre>
<p>We can still call getHtml() and setHtml() to retrieve and update our html config at any time.</p>
<h2>Subclassing and Custom Configs</h2>
<p>We created a simple subclass above that provided a new default value for Ext.Panel&#8217;s <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.Panel-cfg-html">html config</a>. However, we can also add our own configs to our subclasses:</p>
<pre class="brush: jscript;">
Ext.define('MyApp.CustomPanel', {
    extend: 'Ext.Panel',

    config: {
        html: 'Some html',
        anotherConfig: 'default value'
    }
});
</pre>
<p>The &#8216;anotherConfig&#8217; configuration doesn&#8217;t exist on Ext.Panel so it&#8217;s defined for the first time on MyApp.CustomPanel. This <i>automatically</i> creates our getter and setter functions for us:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel');
myPanel.setAnotherConfig('Something else');
myPanel.getAnotherConfig(); //now returns 'Something else'
</pre>
<p>Notice how the getter and setter names were automatically capitalized to use camelCase like all of the other functions in the framework. This was done automatically, but Sencha Touch 2 does another couple of very nice things for you &#8211; it creates hook functions:</p>
<pre class="brush: jscript;">
Ext.define('MyApp.CustomPanel', {
    extend: 'Ext.Panel',

    config: {
        html: 'Some html',
        anotherConfig: 'default value'
    },

    applyAnotherConfig: function(value) {
        return &quot;[TEST] &quot; + value;
    },

    updateAnotherConfig: function(value, oldValue) {
        this.setHtml(&quot;HTML is now &quot; + value);
    }
});
</pre>
<p>We&#8217;ve added two new functions to our class &#8211; applyAnotherConfig and updateAnotherConfig &#8211; these are both called when we call setAnotherConfig. The first one that is called is applyAnotherConfig. This is passed the value of the configuration (&#8217;default value&#8217; by default in this case) and is given the opportunity to modify it. In this case we&#8217;re prepending &#8220;[TEST] &#8221; to whatever anotherConfig is set to:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel');
myPanel.setAnotherConfig('Something else');
myPanel.getAnotherConfig(); //now returns '[TEST] Something else'
</pre>
<p>The second function, updateAnotherConfig, is called after applyAnotherConfig has had a chance to modify the value and is usually used to effect some other change &#8211; whether it&#8217;s updating the DOM, sending an AJAX request, or setting another config as we do here.</p>
<p>When we run the code above, as well as &#8216;[TEST] &#8216; being prepended to our anotherConfig configuration, we&#8217;re calling this.setHtml to update the html configuration too. There&#8217;s no limit to what you can do inside these hook functions, just remember the rule &#8211; the apply functions are used to transform new values before they are saved, the update functions are used to perform the actual side-effects of changing the value (e.g. updating the DOM or configuring other classes).</p>
<h2>How we use it</h2>
<p>The example above is a little contrived to show the point &#8211; let&#8217;s look at a <a href="http://docs.sencha.com/touch/2-0/source/Panel.html#Ext-Panel">real example</a> from Sencha Touch 2&#8217;s Ext.Panel class:</p>
<pre class="brush: jscript;">
applyBodyPadding: function(bodyPadding) {
    if (bodyPadding === true) {
        bodyPadding = 5;
    }

    bodyPadding = Ext.dom.Element.unitizeBox(bodyPadding);

    return bodyPadding;
},

updateBodyPadding: function(newBodyPadding) {
    this.element.setStyle('padding', newBodyPadding);
}
</pre>
<p>Here we see the apply and update functions for the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.Panel-cfg-bodyPadding">bodyPadding</a> config. Notice that in the applyBodyPadding function we set a default and use the framework&#8217;s unitizeBox function to parse CSS padding strings (like &#8216;5px 5px 10px 15px&#8217;) into top, left, bottom and right paddings, which we then return as the transformed value.</p>
<p>The updateBodyPadding then takes this modified value and performs the actual updates &#8211; in this case setting the padding style on the Panel&#8217;s element based on the new configuration. You can see similar usage in almost any component class in the framework.</p>
<h2>Find out more</h2>
<p>This is just a look through the most important aspects of the new class system and how they impact you when writing apps in Sencha Touch 2. To find out more about the class system we recommend taking a look at the <a href="http://docs.sencha.com/touch/2-0/#!/guide/class_system">Class System guide</a> and if you have any questions the <a href="http://www.sencha.com/forum/forumdisplay.php?90-Sencha-Touch-2.x-Q-amp-A">forums</a> are a great place to start.</p>
]]></description>
			<content:encoded><![CDATA[<p>Sencha Touch 1 used the class system from Ext JS 3, which provides a simple but powerful inheritance system that makes it easier to write big complex things like applications and frameworks.</p>
<p>With Sencha Touch 2 we&#8217;ve taken Ext JS 4&#8217;s much more advanced class system and used it to create a leaner, cleaner and more beautiful framework. This post takes you through what has changed and how to use it to improve your apps.</p>
<h2>Syntax</h2>
<p>The first thing you&#8217;ll notice when comparing code from 1.x and 2.x is that the class syntax is different. Back in 1.x we would define a class like this:</p>
<pre class="brush: jscript;">
MyApp.CustomPanel = Ext.extend(Ext.Panel, {
    html: 'Some html'
});
</pre>
<p>This would create a subclass of Ext.Panel called MyApp.CustomPanel, setting the html configuration to &#8216;Some html&#8217;. Any time we create a new instance of our subclass (by calling new MyApp.CustomPanel()), we&#8217;ll now get a slightly customized Ext.Panel instance.</p>
<p>Now let&#8217;s see how the same class is defined in Sencha Touch 2:</p>
<pre class="brush: jscript;">
Ext.define('MyApp.CustomPanel', {
    extend: 'Ext.Panel',

    config: {
        html: 'Some html'
    }
});
</pre>
<p>There are a few changes here, let&#8217;s go through them one by one. Firstly and most obviously we&#8217;ve swapped out Ext.extend for Ext.define. Ext.define operates using strings &#8211; notice that both &#8216;MyApp.CustomPanel&#8217; and &#8216;Ext.Panel&#8217; are now wrapped in quotes. This enables one of the most powerful parts of the new class system &#8211; dynamic loading.</p>
<p>I actually talked about this in a post about Ext JS 4 last year so if you&#8217;re not familiar you should <a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">check out the post</a>, but in a nutshell Sencha Touch 2 will automatically ensure that the class you&#8217;re extending (Ext.Panel) is loaded on the page, fetching it from your server if necessary. This makes development easier and enables you to create custom builds that only contain the class your app actually uses.</p>
<p>The second notable change is that we&#8217;re using a &#8216;config&#8217; block now. Configs are a special thing in Sencha Touch 2 &#8211; they are properties of a class that can be retrieved and updated at any time, and provide extremely useful hook functions that enable you to run any custom logic you like whenever one of them is changed.</p>
<p>Whenever you want to customize any of the configurations of a subclass in Sencha Touch 2, just place them in the config block and the framework takes care of the rest, as we&#8217;ll see in a moment.</p>
<h2>Consistency</h2>
<p>The biggest improvement that comes from the config system is consistency. Let&#8217;s take our MyApp.CustomPanel class above and create an instance of it:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel');
</pre>
<p>Every configuration has an automatically generated getter and setter function, which we can use like this:</p>
<pre class="brush: jscript;">
myPanel.setHtml('New HTML');
myPanel.getHtml(); //returns 'New HTML'
</pre>
<p>This might not seem much, but the convention applies to every single configuration in the entire framework. This eliminates the guesswork from the API &#8211; if you know the config name, you know how to get it and update it. Contrast this with Sencha Touch 1 where retrieving the html config meant finding some property on the instance, and updating it meant calling myPanel.update(&#8217;New HTML&#8217;), which is nowhere near as predictable.</p>
<h2>Instantiating</h2>
<p>You probably noticed that we used a new function above &#8211; Ext.create. This is very similar to just calling &#8216;new MyApp.CustomPanel()&#8217;, with the exception that Ext.create uses the dynamic loading system to automatically load the class you are trying to instantiate if it is not already on the page. This can make life much easier when developing your app as you don&#8217;t have to immediately manage dependencies &#8211; it just works.</p>
<p>In the example above we just instantiated a default MyApp.CustomPanel but of course we can customize it at instantiation time by passing configs into Ext.create:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel', {
    html: 'Some Custom HTML'
});
</pre>
<p>We can still call getHtml() and setHtml() to retrieve and update our html config at any time.</p>
<h2>Subclassing and Custom Configs</h2>
<p>We created a simple subclass above that provided a new default value for Ext.Panel&#8217;s <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.Panel-cfg-html">html config</a>. However, we can also add our own configs to our subclasses:</p>
<pre class="brush: jscript;">
Ext.define('MyApp.CustomPanel', {
    extend: 'Ext.Panel',

    config: {
        html: 'Some html',
        anotherConfig: 'default value'
    }
});
</pre>
<p>The &#8216;anotherConfig&#8217; configuration doesn&#8217;t exist on Ext.Panel so it&#8217;s defined for the first time on MyApp.CustomPanel. This <i>automatically</i> creates our getter and setter functions for us:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel');
myPanel.setAnotherConfig('Something else');
myPanel.getAnotherConfig(); //now returns 'Something else'
</pre>
<p>Notice how the getter and setter names were automatically capitalized to use camelCase like all of the other functions in the framework. This was done automatically, but Sencha Touch 2 does another couple of very nice things for you &#8211; it creates hook functions:</p>
<pre class="brush: jscript;">
Ext.define('MyApp.CustomPanel', {
    extend: 'Ext.Panel',

    config: {
        html: 'Some html',
        anotherConfig: 'default value'
    },

    applyAnotherConfig: function(value) {
        return &quot;[TEST] &quot; + value;
    },

    updateAnotherConfig: function(value, oldValue) {
        this.setHtml(&quot;HTML is now &quot; + value);
    }
});
</pre>
<p>We&#8217;ve added two new functions to our class &#8211; applyAnotherConfig and updateAnotherConfig &#8211; these are both called when we call setAnotherConfig. The first one that is called is applyAnotherConfig. This is passed the value of the configuration (&#8217;default value&#8217; by default in this case) and is given the opportunity to modify it. In this case we&#8217;re prepending &#8220;[TEST] &#8221; to whatever anotherConfig is set to:</p>
<pre class="brush: jscript;">
var myPanel = Ext.create('MyApp.CustomPanel');
myPanel.setAnotherConfig('Something else');
myPanel.getAnotherConfig(); //now returns '[TEST] Something else'
</pre>
<p>The second function, updateAnotherConfig, is called after applyAnotherConfig has had a chance to modify the value and is usually used to effect some other change &#8211; whether it&#8217;s updating the DOM, sending an AJAX request, or setting another config as we do here.</p>
<p>When we run the code above, as well as &#8216;[TEST] &#8216; being prepended to our anotherConfig configuration, we&#8217;re calling this.setHtml to update the html configuration too. There&#8217;s no limit to what you can do inside these hook functions, just remember the rule &#8211; the apply functions are used to transform new values before they are saved, the update functions are used to perform the actual side-effects of changing the value (e.g. updating the DOM or configuring other classes).</p>
<h2>How we use it</h2>
<p>The example above is a little contrived to show the point &#8211; let&#8217;s look at a <a href="http://docs.sencha.com/touch/2-0/source/Panel.html#Ext-Panel">real example</a> from Sencha Touch 2&#8217;s Ext.Panel class:</p>
<pre class="brush: jscript;">
applyBodyPadding: function(bodyPadding) {
    if (bodyPadding === true) {
        bodyPadding = 5;
    }

    bodyPadding = Ext.dom.Element.unitizeBox(bodyPadding);

    return bodyPadding;
},

updateBodyPadding: function(newBodyPadding) {
    this.element.setStyle('padding', newBodyPadding);
}
</pre>
<p>Here we see the apply and update functions for the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.Panel-cfg-bodyPadding">bodyPadding</a> config. Notice that in the applyBodyPadding function we set a default and use the framework&#8217;s unitizeBox function to parse CSS padding strings (like &#8216;5px 5px 10px 15px&#8217;) into top, left, bottom and right paddings, which we then return as the transformed value.</p>
<p>The updateBodyPadding then takes this modified value and performs the actual updates &#8211; in this case setting the padding style on the Panel&#8217;s element based on the new configuration. You can see similar usage in almost any component class in the framework.</p>
<h2>Find out more</h2>
<p>This is just a look through the most important aspects of the new class system and how they impact you when writing apps in Sencha Touch 2. To find out more about the class system we recommend taking a look at the <a href="http://docs.sencha.com/touch/2-0/#!/guide/class_system">Class System guide</a> and if you have any questions the <a href="http://www.sencha.com/forum/forumdisplay.php?90-Sencha-Touch-2.x-Q-amp-A">forums</a> are a great place to start.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2012/01/the-class-system-in-sencha-touch-2-what-you-need-to-know.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sencha Touch 2 PR4 &#8211; Big Improvements in Data and MVC</title>
		<link>http://edspencer.net/2012/01/sencha-touch-2-pr4-big-improvements-in-data-and-mvc.html</link>
		<comments>http://edspencer.net/2012/01/sencha-touch-2-pr4-big-improvements-in-data-and-mvc.html#comments</comments>
		<pubDate>Tue, 24 Jan 2012 08:59:44 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=659</guid>
		<description><![CDATA[<p>Today <a href="http://www.sencha.com/forum/announcement.php?f=92&#038;a=28">we released Sencha Touch 2.0 PR4</a> &#8211; the fourth and final preview release before we hit beta. While we&#8217;re technically calling this one a preview release, we&#8217;re pretty happy with the performance, stability and overall quality of this release and consider it exceptionally close to beta quality.</p>
<p>As well as a good number of <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/release-notes.html">enhancements and bug fixes</a> PR4 brings a couple of long-awaited improvements to two of the most important parts of Sencha Touch &#8211; the data package and the application architecture.</p>
<p>First up, the data package has been ported to use the new config system, which normalizes all of the configuration options for every class in the data package, providing a clean and predictable way to configure and update your data classes. We&#8217;re still cleaning up some of the data package documentation and given the scope of some of the changes we&#8217;re expecting a few bugs to appear as a result but overall we&#8217;re very happy with the improved capabilities of Ext.data.</p>
<h2>MVC Improvements</h2>
<p>The second big improvement in PR4 is to the application architecture. The MVC classes have also been upgraded to use the new config system, again yielding big improvements in the API and general flexibility of your code.</p>
<p>History support has been baked directly into <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.app.Controller">Controllers</a>, enabling you to easily define routes that your Controller cares about, as well as the functions that handle those routes right there in your Controller file. The <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink">Kitchen Sink example</a> has been upgraded to use routes out of the box &#8211; try it on a mobile device or desktop browser and watch how it reacts to the back/forward buttons.</p>
<p>Equally important, <a href="http://docs.sencha.com/touch/2-0/#!/guide/profiles">Device Profiles</a> have been upgraded to make creating apps that adapt to different screen sizes much simpler than ever before. Once again the <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink">Kitchen Sink</a> has been upgraded to take advantage of device profiles. If you load it on a tablet device you&#8217;ll see a split screen view with the menu on the left and the content on the right, whereas the phone version employs a nested list to save screen space.</p>
<p>To cap it off the deep linking support means you can navigate to any view on a phone, send the link to a friend on a tablet and they&#8217;ll be taken to the same view customized for their screen size. As an example, try opening <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink/#demo/forms">http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink/#demo/forms</a> on a tablet and a phone to see it show the Forms demo specialized for each type of device.</p>
<p>As PR4 is the first time we&#8217;ve exposed this expanded functionality to the public we expect that there will be bugs and edge cases that crop up. We&#8217;ll be keeping a close eye on the bug forums and addressing any issues as quickly as possible, as well as creating additional MVC-driven examples for you to learn from. For now, the kitchen sink is the best example of Sencha Touch 2 MVC in action.</p>
<h2>Docs</h2>
<p>We&#8217;ve made a huge push over the last couple of years to radically improve our documentation, and I think that even in the pre-beta PR4 release Sencha Touch 2 has the best docs we&#8217;ve ever created. While there are still holes to be filled in, we already ship with <a href="http://docs.sencha.com/touch/2-0/#!/guide">20 guides on how to use the framework</a>, including 4 brand new guides for PR4:</p>
<ul>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/upgrade_1_to_2">Migrating from 1.x</a></li>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/apps_intro">Intro to MVC</a></li>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/profiles">Using Device Profiles</a></li>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/controllers">Using Controllers</a></li>
</ul>
<p>As well as the guides, most of the classes now contain generous documentation explaining their function and the context in which they operate. As we move to beta and then to GA we&#8217;ll be shifting our focus onto producing great demos and examples to showcase the framework&#8217;s capabilities and provide realistic sample code to draw from.</p>
<p>There&#8217;s a full set of <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/release-notes.html">release notes</a> explaining the improvements in PR4 and the important known issues. We expect to be shipping regular releases from now until GA so be sure to keep an eye on the forums, twitter and the <a href="http://sencha.com/blog">sencha blog</a> for more details.</p>
]]></description>
			<content:encoded><![CDATA[<p>Today <a href="http://www.sencha.com/forum/announcement.php?f=92&#038;a=28">we released Sencha Touch 2.0 PR4</a> &#8211; the fourth and final preview release before we hit beta. While we&#8217;re technically calling this one a preview release, we&#8217;re pretty happy with the performance, stability and overall quality of this release and consider it exceptionally close to beta quality.</p>
<p>As well as a good number of <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/release-notes.html">enhancements and bug fixes</a> PR4 brings a couple of long-awaited improvements to two of the most important parts of Sencha Touch &#8211; the data package and the application architecture.</p>
<p>First up, the data package has been ported to use the new config system, which normalizes all of the configuration options for every class in the data package, providing a clean and predictable way to configure and update your data classes. We&#8217;re still cleaning up some of the data package documentation and given the scope of some of the changes we&#8217;re expecting a few bugs to appear as a result but overall we&#8217;re very happy with the improved capabilities of Ext.data.</p>
<h2>MVC Improvements</h2>
<p>The second big improvement in PR4 is to the application architecture. The MVC classes have also been upgraded to use the new config system, again yielding big improvements in the API and general flexibility of your code.</p>
<p>History support has been baked directly into <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.app.Controller">Controllers</a>, enabling you to easily define routes that your Controller cares about, as well as the functions that handle those routes right there in your Controller file. The <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink">Kitchen Sink example</a> has been upgraded to use routes out of the box &#8211; try it on a mobile device or desktop browser and watch how it reacts to the back/forward buttons.</p>
<p>Equally important, <a href="http://docs.sencha.com/touch/2-0/#!/guide/profiles">Device Profiles</a> have been upgraded to make creating apps that adapt to different screen sizes much simpler than ever before. Once again the <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink">Kitchen Sink</a> has been upgraded to take advantage of device profiles. If you load it on a tablet device you&#8217;ll see a split screen view with the menu on the left and the content on the right, whereas the phone version employs a nested list to save screen space.</p>
<p>To cap it off the deep linking support means you can navigate to any view on a phone, send the link to a friend on a tablet and they&#8217;ll be taken to the same view customized for their screen size. As an example, try opening <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink/#demo/forms">http://dev.sencha.com/deploy/sencha-touch-2-pr4/examples/kitchensink/#demo/forms</a> on a tablet and a phone to see it show the Forms demo specialized for each type of device.</p>
<p>As PR4 is the first time we&#8217;ve exposed this expanded functionality to the public we expect that there will be bugs and edge cases that crop up. We&#8217;ll be keeping a close eye on the bug forums and addressing any issues as quickly as possible, as well as creating additional MVC-driven examples for you to learn from. For now, the kitchen sink is the best example of Sencha Touch 2 MVC in action.</p>
<h2>Docs</h2>
<p>We&#8217;ve made a huge push over the last couple of years to radically improve our documentation, and I think that even in the pre-beta PR4 release Sencha Touch 2 has the best docs we&#8217;ve ever created. While there are still holes to be filled in, we already ship with <a href="http://docs.sencha.com/touch/2-0/#!/guide">20 guides on how to use the framework</a>, including 4 brand new guides for PR4:</p>
<ul>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/upgrade_1_to_2">Migrating from 1.x</a></li>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/apps_intro">Intro to MVC</a></li>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/profiles">Using Device Profiles</a></li>
<li><a href="http://docs.sencha.com/touch/2-0/#!/guide/controllers">Using Controllers</a></li>
</ul>
<p>As well as the guides, most of the classes now contain generous documentation explaining their function and the context in which they operate. As we move to beta and then to GA we&#8217;ll be shifting our focus onto producing great demos and examples to showcase the framework&#8217;s capabilities and provide realistic sample code to draw from.</p>
<p>There&#8217;s a full set of <a href="http://dev.sencha.com/deploy/sencha-touch-2-pr4/release-notes.html">release notes</a> explaining the improvements in PR4 and the important known issues. We expect to be shipping regular releases from now until GA so be sure to keep an eye on the forums, twitter and the <a href="http://sencha.com/blog">sencha blog</a> for more details.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2012/01/sencha-touch-2-pr4-big-improvements-in-data-and-mvc.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SenchaCon 2011: The Best Bits</title>
		<link>http://edspencer.net/2011/10/senchacon-2011-the-best-bits.html</link>
		<comments>http://edspencer.net/2011/10/senchacon-2011-the-best-bits.html#comments</comments>
		<pubDate>Wed, 26 Oct 2011 21:46:42 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=650</guid>
		<description><![CDATA[<p>SenchaCon 2011 is drawing to a close and it&#8217;s been another awesome ride. We were joined by 600 of the best and brightest of the Sencha community and I think it&#8217;s pretty safe to say we had an awesome time. Day 3 is just drawing to a close so here&#8217;s a few highlights from the week.</p>
<h2>Ext JS 4.1 Performance Preview Released</h2>
<p>There were a number of big announcements on day 1. Probably the most exciting one for me was the release of <a href="http://www.sencha.com/blog/ext-js-4-1-developer-preview">Ext JS 4.1 Performance Preview</a>. We&#8217;ve been working like fiends to improve Ext JS&#8217;s performance profile on older browsers (IE6, IE7 and IE8 in particular) and on Monday we were able to share some of what we&#8217;ve achieved.</p>
<p>Page load, render and layout times are all enormously improved and have been the focus of our optimizations so far. Since 4.0 we&#8217;ve been building up a performance benchmarking rig that tests all of our 100+ examples (and a number of real-world customer apps) on consumer grade hardware with a range of browsers. We&#8217;ve seen massive improvements in loading time on these older browsers &#8211; for example the Themes Viewer example with its 300 Components all rendered at load time now starts up twice as fast as it did in 4.0.7.</p>
<p>To give a flavor for the breadth of the improvement we ran the tests on every example and summed up the loading time for each browser. As you can see below, 4.1 is able to speed through all of the examples significantly faster than 4.0.7, giving a massive performance boost across the board. It got so much faster that IE8 is now able to load all 100+ examples in a little under 20 seconds, compared with almost 60 in 4.0.7:</p>
<p><img src="http://img1.sencha.com/files/misc/IE-performance-on-4.0.7-vs-4.1.png" /></p>
<p><a href="http://www.sencha.com/blog/ext-js-4-1-developer-preview/">See the full announcement</a> on the sencha.com blog, but like we said there, this is a pre-beta release with a number of known issues. We&#8217;d love for you to verify the speed improvements with your own apps but please don&#8217;t take it anywhere near production yet! We&#8217;ll have more content on what&#8217;s in 4.1 in later blog posts.</p>
<h2>Other Announcements</h2>
<p>While Ext JS is closest to my heart, there were a number of other announcements made over the last few days. First up is Sencha.IO, our new cloud service and <a href="http://www.sencha.com/blog/introducing-sencha-io-the-first-mobile-html5-cloud/">now launching in beta</a>. This is a set of 4 services &#8211; data, messages, login and app deployment &#8211; that make creating and deploying web apps a snap, especially when you integrate the social aspects of Sencha.IO data and messages.</p>
<p>We also announced that we&#8217;ve just closed a second round of funding, raising another $15 million to further advance the state of the art in HTML5 technologies. This is going to enable us to push forward even faster and bring you some exciting new technologies. It was great that Sequoia Capital and Radar Partners were so happy with their first round with us that they decided to invest again. The future is definitely very exciting at Sencha right now.</p>
<h2>Favorite Sessions</h2>
<p>There were over 50 sessions this year and with several tracks going on simultaneously it was impossible to go to them all. Jacky Nguyen definitely stole the show with his talk on the Sencha Class System. He has a ridiculously over the top presentation style and totally brought the house down. We&#8217;ll be sure to get him on stage more often!</p>
<p>Jamie and Nicolas&#8217; talk on charting was very cool and generated lots of spontaneous applause (that happened a lot during the conference, which must be a good thing), and Rob and Dave&#8217;s demonstration of styling using the new beta Neptune theme was equally awesome.</p>
<p>Don lit the place up with his talk detailing the work that went into making Ext JS 4.1 so much faster, along with all the other new features in the release. Another mind blowing talk was given by John Willander, who demo&#8217;d a series of client-side attacks along with the <a href="http://beefproject.com/">BeEF Project</a>, which happens to be writen in Ext JS. Based on what John presented we&#8217;ll definitely be looking at what we can do to help you secure your apps with Ext JS.</p>
<p>Of course, I had a couple of sessions myself, though a few technical problems early on made them rather more challenging than expected (it&#8217;s hard to talk to people when your microphone cuts out after every second word!). The Intro to MVC talk was a blast and the sacrifice to the gods of live demos seemed to pay off as the 20 minute live coding session went without a hitch. Anyone who wants the code I put together during that session can find it <a href="https://github.com/edspencer/SenchaConDemo">up on github</a>.</p>
<h2>Meeting Everyone</h2>
<p>Although there were 600 people here this time it felt like I was able to meet almost everyone. Your intense enthusiasm for what we do really came through and to everyone who came up and gave us such great feedback it really drives us forward to keep improving your framework so thank you!</p>
<p>I saw more awesome Ext JS and Sencha Touch apps than I could count, and was pleasantly surprised to see how many people had been able to construct full applications using Sencha Touch 2 despite it only being <a href="http://www.sencha.com/blog/sencha-touch-2-developer-preview/">in Developer Preview</a> right now. It was also great getting to spend time hanging out with people and seeing them get excited when they start to see what&#8217;s possible with these products. Spending time in the flesh with developers is probably the most important part of the whole conference so it was great to meet so many of you.</p>
<p>Finally, Grgur announced that the second SourceCon Europe will be taking place in London around April of next year. The first SourceCon was an awesome experience in beautiful Split, Croatia, and next year we&#8217;ll be heading to London, England for this community-organized, Sencha-centric conference. They&#8217;ll be launching the conference website in a couple of weeks and given how good it was last year you&#8217;ll probably have to rush to get your tickets. Hope to see you there!</p>
]]></description>
			<content:encoded><![CDATA[<p>SenchaCon 2011 is drawing to a close and it&#8217;s been another awesome ride. We were joined by 600 of the best and brightest of the Sencha community and I think it&#8217;s pretty safe to say we had an awesome time. Day 3 is just drawing to a close so here&#8217;s a few highlights from the week.</p>
<h2>Ext JS 4.1 Performance Preview Released</h2>
<p>There were a number of big announcements on day 1. Probably the most exciting one for me was the release of <a href="http://www.sencha.com/blog/ext-js-4-1-developer-preview">Ext JS 4.1 Performance Preview</a>. We&#8217;ve been working like fiends to improve Ext JS&#8217;s performance profile on older browsers (IE6, IE7 and IE8 in particular) and on Monday we were able to share some of what we&#8217;ve achieved.</p>
<p>Page load, render and layout times are all enormously improved and have been the focus of our optimizations so far. Since 4.0 we&#8217;ve been building up a performance benchmarking rig that tests all of our 100+ examples (and a number of real-world customer apps) on consumer grade hardware with a range of browsers. We&#8217;ve seen massive improvements in loading time on these older browsers &#8211; for example the Themes Viewer example with its 300 Components all rendered at load time now starts up twice as fast as it did in 4.0.7.</p>
<p>To give a flavor for the breadth of the improvement we ran the tests on every example and summed up the loading time for each browser. As you can see below, 4.1 is able to speed through all of the examples significantly faster than 4.0.7, giving a massive performance boost across the board. It got so much faster that IE8 is now able to load all 100+ examples in a little under 20 seconds, compared with almost 60 in 4.0.7:</p>
<p><img src="http://img1.sencha.com/files/misc/IE-performance-on-4.0.7-vs-4.1.png" /></p>
<p><a href="http://www.sencha.com/blog/ext-js-4-1-developer-preview/">See the full announcement</a> on the sencha.com blog, but like we said there, this is a pre-beta release with a number of known issues. We&#8217;d love for you to verify the speed improvements with your own apps but please don&#8217;t take it anywhere near production yet! We&#8217;ll have more content on what&#8217;s in 4.1 in later blog posts.</p>
<h2>Other Announcements</h2>
<p>While Ext JS is closest to my heart, there were a number of other announcements made over the last few days. First up is Sencha.IO, our new cloud service and <a href="http://www.sencha.com/blog/introducing-sencha-io-the-first-mobile-html5-cloud/">now launching in beta</a>. This is a set of 4 services &#8211; data, messages, login and app deployment &#8211; that make creating and deploying web apps a snap, especially when you integrate the social aspects of Sencha.IO data and messages.</p>
<p>We also announced that we&#8217;ve just closed a second round of funding, raising another $15 million to further advance the state of the art in HTML5 technologies. This is going to enable us to push forward even faster and bring you some exciting new technologies. It was great that Sequoia Capital and Radar Partners were so happy with their first round with us that they decided to invest again. The future is definitely very exciting at Sencha right now.</p>
<h2>Favorite Sessions</h2>
<p>There were over 50 sessions this year and with several tracks going on simultaneously it was impossible to go to them all. Jacky Nguyen definitely stole the show with his talk on the Sencha Class System. He has a ridiculously over the top presentation style and totally brought the house down. We&#8217;ll be sure to get him on stage more often!</p>
<p>Jamie and Nicolas&#8217; talk on charting was very cool and generated lots of spontaneous applause (that happened a lot during the conference, which must be a good thing), and Rob and Dave&#8217;s demonstration of styling using the new beta Neptune theme was equally awesome.</p>
<p>Don lit the place up with his talk detailing the work that went into making Ext JS 4.1 so much faster, along with all the other new features in the release. Another mind blowing talk was given by John Willander, who demo&#8217;d a series of client-side attacks along with the <a href="http://beefproject.com/">BeEF Project</a>, which happens to be writen in Ext JS. Based on what John presented we&#8217;ll definitely be looking at what we can do to help you secure your apps with Ext JS.</p>
<p>Of course, I had a couple of sessions myself, though a few technical problems early on made them rather more challenging than expected (it&#8217;s hard to talk to people when your microphone cuts out after every second word!). The Intro to MVC talk was a blast and the sacrifice to the gods of live demos seemed to pay off as the 20 minute live coding session went without a hitch. Anyone who wants the code I put together during that session can find it <a href="https://github.com/edspencer/SenchaConDemo">up on github</a>.</p>
<h2>Meeting Everyone</h2>
<p>Although there were 600 people here this time it felt like I was able to meet almost everyone. Your intense enthusiasm for what we do really came through and to everyone who came up and gave us such great feedback it really drives us forward to keep improving your framework so thank you!</p>
<p>I saw more awesome Ext JS and Sencha Touch apps than I could count, and was pleasantly surprised to see how many people had been able to construct full applications using Sencha Touch 2 despite it only being <a href="http://www.sencha.com/blog/sencha-touch-2-developer-preview/">in Developer Preview</a> right now. It was also great getting to spend time hanging out with people and seeing them get excited when they start to see what&#8217;s possible with these products. Spending time in the flesh with developers is probably the most important part of the whole conference so it was great to meet so many of you.</p>
<p>Finally, Grgur announced that the second SourceCon Europe will be taking place in London around April of next year. The first SourceCon was an awesome experience in beautiful Split, Croatia, and next year we&#8217;ll be heading to London, England for this community-organized, Sencha-centric conference. They&#8217;ll be launching the conference website in a couple of weeks and given how good it was last year you&#8217;ll probably have to rush to get your tickets. Hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/10/senchacon-2011-the-best-bits.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ext JS 4.0.7 Released</title>
		<link>http://edspencer.net/2011/10/ext-js-4-0-7-released.html</link>
		<comments>http://edspencer.net/2011/10/ext-js-4-0-7-released.html#comments</comments>
		<pubDate>Thu, 20 Oct 2011 19:21:38 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=647</guid>
		<description><![CDATA[<p>I&#8217;m very happy to report that we released Ext JS 4.0.7 to the public today. This is the seventh patch release to the 4.0.x series and contains several hundred improvements and bug fixes compared to the last public version, 4.0.2a.</p>
<p>4.0.7 is all about robustness &#8211; we&#8217;ve found that our support subscribers have had a lot of success with the newer builds of Ext JS 4 so I&#8217;m really pleased that we can share this with you. We&#8217;re releasing this publicly earlier than we would usually do because it has taken us longer than we expected to get Ext JS 4.1 into your hands.</p>
<p>Michael put out <a href="http://www.sencha.com/blog/ext-js-4-1-update/">a post on our blog</a> last week with some updates on 4.1 and our desires around releases and communications with the community. Not being able to ship 4.1 to you yet has been a frustrating experience but I think that once you see it you&#8217;ll enjoy the vast improvements it brings.</p>
<p>In the meantime, I&#8217;m happy to answer questions in the comments, via twitter or email (ed @ sencha). You can <a href="http://www.sencha.com/products/extjs/download">download the build here</a> and see the <a href="http://dev.sencha.com/deploy/ext-4.0.7-gpl/release-notes.html">full release notes for 4.0.7</a> all the way back to 4.0.0.</p>
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m very happy to report that we released Ext JS 4.0.7 to the public today. This is the seventh patch release to the 4.0.x series and contains several hundred improvements and bug fixes compared to the last public version, 4.0.2a.</p>
<p>4.0.7 is all about robustness &#8211; we&#8217;ve found that our support subscribers have had a lot of success with the newer builds of Ext JS 4 so I&#8217;m really pleased that we can share this with you. We&#8217;re releasing this publicly earlier than we would usually do because it has taken us longer than we expected to get Ext JS 4.1 into your hands.</p>
<p>Michael put out <a href="http://www.sencha.com/blog/ext-js-4-1-update/">a post on our blog</a> last week with some updates on 4.1 and our desires around releases and communications with the community. Not being able to ship 4.1 to you yet has been a frustrating experience but I think that once you see it you&#8217;ll enjoy the vast improvements it brings.</p>
<p>In the meantime, I&#8217;m happy to answer questions in the comments, via twitter or email (ed @ sencha). You can <a href="http://www.sencha.com/products/extjs/download">download the build here</a> and see the <a href="http://dev.sencha.com/deploy/ext-4.0.7-gpl/release-notes.html">full release notes for 4.0.7</a> all the way back to 4.0.0.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/10/ext-js-4-0-7-released.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Sencha Touch 2 &#8211; Thoughts from the Trenches</title>
		<link>http://edspencer.net/2011/10/sencha-touch-2-thoughts-from-the-trenches.html</link>
		<comments>http://edspencer.net/2011/10/sencha-touch-2-thoughts-from-the-trenches.html#comments</comments>
		<pubDate>Tue, 11 Oct 2011 21:01:43 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[extjs]]></category>
		<category><![CDATA[touch]]></category>
		<category><![CDATA[preview]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[sencha]]></category>
		<category><![CDATA[sencha touch]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=641</guid>
		<description><![CDATA[<p>As you may have seen, we put out the first public preview release of Sencha Touch 2 today. It only went live a few hours ago but the feedback has been inspiring so far. For the full scoop see <a href="http://www.sencha.com/blog/sencha-touch-2-developer-preview/">the post on the sencha.com blog</a>. A few thoughts on where we are with the product:</p>
<h2>Performance</h2>
<p>Performance on Android devices in particular is breathtaking. I never thought I&#8217;d see the day where I could pick up an Android 2.3 device and have it feel faster than an iPhone 4, and yet that&#8217;s exactly what Sencha Touch 2 brings to the table. I recorded this short video on an actual device to show real world performance:</p>
<p><a href="http://vimeo.com/30324079"><img src="http://img1.sencha.com/files/misc/20111010-video-sm.jpg" /></a></p>
<p>Now try the same on Sencha Touch 1.x (or any other competing framework) and (if you&#8217;re anything like me) cringe at what we were accustomed to using before. That video&#8217;s cool, but the one that&#8217;s really driving people wild is the side by side comparison of the layout engines in 1.x and 2.x.</p>
<p>Getting our hands on a high speed camera and recording these devices at 120fps was a lot of fun. Slowing time down to 1/4 of normal speed shows just how much faster the new layout engine is than what we used to have:</p>
<p><a href="http://vimeo.com/30296006"><img src="http://img1.sencha.com/files/misc/20111010-video-full.jpg" /></a></p>
<p>The most amazing part here is that we actually finish laying out *before* the phone&#8217;s rotation animation has completed. Skipping through the video frame by frame there are at least 5 frames where the app is fully laid out and interactive while the phone&#8217;s rotation animation is still running. Beating the phone&#8217;s own rotation speed is the holy grail &#8211; it&#8217;s not possible to make it any faster.</p>
<h2>Documentation</h2>
<p>I&#8217;ll admit it, I&#8217;m fanatical about <a href="http://docs.sencha.com/touch/2-0/#">great documentation</a>. I&#8217;m sure I drive everyone else on the team crazy but I think it&#8217;s worth it. This is only a preview release but it already contains by far the best, most complete documentation we&#8217;ve ever shipped in an initial release.</p>
<p>In fact, the team&#8217;s worked so hard on documenting classes that it&#8217;s probably better than the (already good) <a href="http://docs.sencha.com/ext-js/4-0">Ext JS 4 docs</a>. Naturally, this makes it time to further improve the Ext JS documentation.</p>
<p>We&#8217;ve added some awesome features here &#8211; lots of videos, 11 brand new guides and illustrations. My favourite new feature is definitely the inline examples with live previews though &#8211; seeing Sencha Touch running live in a phone/tablet right there in the docs is just amazing. Little gems like the live twitter feed in the bottom-most example in the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.dataview.DataView">DataView docs</a> really sell just how easy it is to configure these components.</p>
<p>We set a high bar for this though. We&#8217;ve gone from woeful documentation in 1.x to good documentation in 2.x, but what we&#8217;re shooting for is excellence. We&#8217;ll continue to round out our content over coming weeks, and have a few new features rolling out soon that will raise the bar once again.</p>
<h2>Onwards</h2>
<p>We have a few features left to implement, which is why we&#8217;re calling this preview and not beta. Probably the biggest thing now is getting routing/deep linking back into the framework, along with a nice new syntax that I think you&#8217;ll find really easy to use. We&#8217;re also missing carousel animations and a handful of other things that will be going back in over the coming weeks. We have Sencha Con 2011 in just 12 days now though so we&#8217;ll share more details there.</p>
<p>Finally though, I want to thank everyone who participated in the closed preview phase, and for everyone sending their support and kind words on the blog, the forums and on twitter. We really appreciate all the great feedback and I hope we can exceed your expectations with a fast, polished, gorgeous 2.0 final!</p>
]]></description>
			<content:encoded><![CDATA[<p>As you may have seen, we put out the first public preview release of Sencha Touch 2 today. It only went live a few hours ago but the feedback has been inspiring so far. For the full scoop see <a href="http://www.sencha.com/blog/sencha-touch-2-developer-preview/">the post on the sencha.com blog</a>. A few thoughts on where we are with the product:</p>
<h2>Performance</h2>
<p>Performance on Android devices in particular is breathtaking. I never thought I&#8217;d see the day where I could pick up an Android 2.3 device and have it feel faster than an iPhone 4, and yet that&#8217;s exactly what Sencha Touch 2 brings to the table. I recorded this short video on an actual device to show real world performance:</p>
<p><a href="http://vimeo.com/30324079"><img src="http://img1.sencha.com/files/misc/20111010-video-sm.jpg" /></a></p>
<p>Now try the same on Sencha Touch 1.x (or any other competing framework) and (if you&#8217;re anything like me) cringe at what we were accustomed to using before. That video&#8217;s cool, but the one that&#8217;s really driving people wild is the side by side comparison of the layout engines in 1.x and 2.x.</p>
<p>Getting our hands on a high speed camera and recording these devices at 120fps was a lot of fun. Slowing time down to 1/4 of normal speed shows just how much faster the new layout engine is than what we used to have:</p>
<p><a href="http://vimeo.com/30296006"><img src="http://img1.sencha.com/files/misc/20111010-video-full.jpg" /></a></p>
<p>The most amazing part here is that we actually finish laying out *before* the phone&#8217;s rotation animation has completed. Skipping through the video frame by frame there are at least 5 frames where the app is fully laid out and interactive while the phone&#8217;s rotation animation is still running. Beating the phone&#8217;s own rotation speed is the holy grail &#8211; it&#8217;s not possible to make it any faster.</p>
<h2>Documentation</h2>
<p>I&#8217;ll admit it, I&#8217;m fanatical about <a href="http://docs.sencha.com/touch/2-0/#">great documentation</a>. I&#8217;m sure I drive everyone else on the team crazy but I think it&#8217;s worth it. This is only a preview release but it already contains by far the best, most complete documentation we&#8217;ve ever shipped in an initial release.</p>
<p>In fact, the team&#8217;s worked so hard on documenting classes that it&#8217;s probably better than the (already good) <a href="http://docs.sencha.com/ext-js/4-0">Ext JS 4 docs</a>. Naturally, this makes it time to further improve the Ext JS documentation.</p>
<p>We&#8217;ve added some awesome features here &#8211; lots of videos, 11 brand new guides and illustrations. My favourite new feature is definitely the inline examples with live previews though &#8211; seeing Sencha Touch running live in a phone/tablet right there in the docs is just amazing. Little gems like the live twitter feed in the bottom-most example in the <a href="http://docs.sencha.com/touch/2-0/#!/api/Ext.dataview.DataView">DataView docs</a> really sell just how easy it is to configure these components.</p>
<p>We set a high bar for this though. We&#8217;ve gone from woeful documentation in 1.x to good documentation in 2.x, but what we&#8217;re shooting for is excellence. We&#8217;ll continue to round out our content over coming weeks, and have a few new features rolling out soon that will raise the bar once again.</p>
<h2>Onwards</h2>
<p>We have a few features left to implement, which is why we&#8217;re calling this preview and not beta. Probably the biggest thing now is getting routing/deep linking back into the framework, along with a nice new syntax that I think you&#8217;ll find really easy to use. We&#8217;re also missing carousel animations and a handful of other things that will be going back in over the coming weeks. We have Sencha Con 2011 in just 12 days now though so we&#8217;ll share more details there.</p>
<p>Finally though, I want to thank everyone who participated in the closed preview phase, and for everyone sending their support and kind words on the blog, the forums and on twitter. We really appreciate all the great feedback and I hope we can exceed your expectations with a fast, polished, gorgeous 2.0 final!</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/10/sencha-touch-2-thoughts-from-the-trenches.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>SourceDevCon 2011 &#8211; an awesome conference</title>
		<link>http://edspencer.net/2011/05/sourcedevcon-2011-an-awesome-conference.html</link>
		<comments>http://edspencer.net/2011/05/sourcedevcon-2011-an-awesome-conference.html#comments</comments>
		<pubDate>Tue, 10 May 2011 22:11:42 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=619</guid>
		<description><![CDATA[<p>The inaugural <a href="http://www.sourcedevcon.eu/">SouceDevCon</a> just wrapped up in Split, Croatia so I&#8217;d like to share a few thoughts on the last few days. The conference was an enormous success, featuring some great speakers, inspiring presentations and a fantastic group of attendees. Split itself is beautiful, and the weather was equally equitable. More than a few of us are returning a lot browner/redder than we came.</p>
<p><a href="http://www.flickr.com/photos/nils-dehl/sets/72157626533490549/"><img src="http://farm6.static.flickr.com/5143/5696912895_5bd7b3c58b_z.jpg" alt="Grgur" title="Grgur" width="640" height="424" class="aligncenter size-full wp-image-625" /></a></p>
<h2>Day 1</h2>
<p>The conference was spread across 3 days &#8211; the first two were spent listening and learning across the three concurrent tracks, the third on a boat sailing around the Adriatic Sea. Day one kicked off with my colleagues Aditya and James setting out a little of what to expect from Sencha in 2011 in the opening keynote.</p>
<p>Straight after that I took to the stage to introduce a few of the features of Ext JS 4. My session started a little late and I forgot what I was talking about a couple of times (sorry guys <img src='http://edspencer.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) but I think it turned out well enough. I spliced together the deadly combination of sleep deprivation and live coding but with a little help from the audience we were able to stumble through. I think it would make for a good screencast.</p>
<p>Aditya came on next and introduced our new Sencha.IO services, which seem to have garnered a lot of interest. James showed off the new Ext JS 4 theming support using SASS and Compass and Nils Dehl did a great job explaining the Ext.data and Ext.direct packages. Jay Garcia gave a well-received talk on creating extensions and plugins, during which I think a lot of people learned a great deal about how classes work in Ext JS 4. I also very much enjoyed Tomislav Car&#8217;s investigation into getting Sencha Touch to run on phones other than Androids and iPhones.</p>
<p>Day 1 ended with a long party (I counted at least 8 hours) with inordinate amounts of Croatian beer, which went down very well. It was great meeting so many new people and hearing how much people are getting out of Ext JS and Sencha Touch, as well as what we can improve.</p>
<h2>Day 2</h2>
<p>Day 2 started in a somewhat hungover fashion with some awesome material from our very own Brian Moeskau, who demonstrated how to use the 3.x -> 4.x compatibility file, upgrading an application from 3.3.1 to 4.0.0 in front of our eyes. Nige (Animal) White demonstrated several of Ext JS&#8217;s layout managers before giving one of the highlights of the conference in his debugging JavaScript presentation (by contrast he calls the introduction of errors into code &#8220;bebugging&#8221;).</p>
<p>Tobias Uhlig showed off FieldManager, a sports centre management management application with a Sencha Touch mobile app, while Matz Bryntse and Brian Moeskau demoed their awesome Scheduler and Calendar components. Josef Sakalos (Saki) spent the afternoon teaching people to use Ext JS 4&#8217;s new MVC package, which makes writing apps a faster and more enjoyable experience. He is an excellent teacher.</p>
<p>Our host the inimitable Grgur finished things off with a typically heartfelt ending keynote to wrap up the business end of the conference. The evening was a great opportunity to see some of Split and spend an enjoyable meal with Croatian locals Tomislav, Miro and the ever-logical Lucia. Unfortunately their attempts to teach me Croatian did not yield much success.</p>
<h2>Day 3</h2>
<p>Day 3 was a stroke of genius by Grgur. We took a chartered boat down to the town and looked around the old Roman-era palace. The boat was well stocked with beer and with so many community members in one place the conversation was pretty lively. All of this relaxing was great but with a head full of ideas I&#8217;m anxious to get back to California and better tune our products based on all the feedback I received this week.</p>
<p>All of the sessions were recorded on video and I believe they&#8217;ll be made available in around a month&#8217;s time. If you can&#8217;t wait until then we have a meetup schedule for<a href="http://www.meetup.com/The-San-Francisco-ExtJS-Meetup-Group/events/17576007/"> May 23rd hosted at Sencha HQ</a> in northern California, to which you&#8217;re all invited. Just in case you&#8217;ve never been to Split before perhaps the sight that greeted us when we arrived will prompt you to get yourself on a flight.</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/05/adriatic.jpg" alt="adriatic" title="adriatic" width="660" height="493" class="aligncenter size-full wp-image-625" /></p>
]]></description>
			<content:encoded><![CDATA[<p>The inaugural <a href="http://www.sourcedevcon.eu/">SouceDevCon</a> just wrapped up in Split, Croatia so I&#8217;d like to share a few thoughts on the last few days. The conference was an enormous success, featuring some great speakers, inspiring presentations and a fantastic group of attendees. Split itself is beautiful, and the weather was equally equitable. More than a few of us are returning a lot browner/redder than we came.</p>
<p><a href="http://www.flickr.com/photos/nils-dehl/sets/72157626533490549/"><img src="http://farm6.static.flickr.com/5143/5696912895_5bd7b3c58b_z.jpg" alt="Grgur" title="Grgur" width="640" height="424" class="aligncenter size-full wp-image-625" /></a></p>
<h2>Day 1</h2>
<p>The conference was spread across 3 days &#8211; the first two were spent listening and learning across the three concurrent tracks, the third on a boat sailing around the Adriatic Sea. Day one kicked off with my colleagues Aditya and James setting out a little of what to expect from Sencha in 2011 in the opening keynote.</p>
<p>Straight after that I took to the stage to introduce a few of the features of Ext JS 4. My session started a little late and I forgot what I was talking about a couple of times (sorry guys <img src='http://edspencer.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) but I think it turned out well enough. I spliced together the deadly combination of sleep deprivation and live coding but with a little help from the audience we were able to stumble through. I think it would make for a good screencast.</p>
<p>Aditya came on next and introduced our new Sencha.IO services, which seem to have garnered a lot of interest. James showed off the new Ext JS 4 theming support using SASS and Compass and Nils Dehl did a great job explaining the Ext.data and Ext.direct packages. Jay Garcia gave a well-received talk on creating extensions and plugins, during which I think a lot of people learned a great deal about how classes work in Ext JS 4. I also very much enjoyed Tomislav Car&#8217;s investigation into getting Sencha Touch to run on phones other than Androids and iPhones.</p>
<p>Day 1 ended with a long party (I counted at least 8 hours) with inordinate amounts of Croatian beer, which went down very well. It was great meeting so many new people and hearing how much people are getting out of Ext JS and Sencha Touch, as well as what we can improve.</p>
<h2>Day 2</h2>
<p>Day 2 started in a somewhat hungover fashion with some awesome material from our very own Brian Moeskau, who demonstrated how to use the 3.x -> 4.x compatibility file, upgrading an application from 3.3.1 to 4.0.0 in front of our eyes. Nige (Animal) White demonstrated several of Ext JS&#8217;s layout managers before giving one of the highlights of the conference in his debugging JavaScript presentation (by contrast he calls the introduction of errors into code &#8220;bebugging&#8221;).</p>
<p>Tobias Uhlig showed off FieldManager, a sports centre management management application with a Sencha Touch mobile app, while Matz Bryntse and Brian Moeskau demoed their awesome Scheduler and Calendar components. Josef Sakalos (Saki) spent the afternoon teaching people to use Ext JS 4&#8217;s new MVC package, which makes writing apps a faster and more enjoyable experience. He is an excellent teacher.</p>
<p>Our host the inimitable Grgur finished things off with a typically heartfelt ending keynote to wrap up the business end of the conference. The evening was a great opportunity to see some of Split and spend an enjoyable meal with Croatian locals Tomislav, Miro and the ever-logical Lucia. Unfortunately their attempts to teach me Croatian did not yield much success.</p>
<h2>Day 3</h2>
<p>Day 3 was a stroke of genius by Grgur. We took a chartered boat down to the town and looked around the old Roman-era palace. The boat was well stocked with beer and with so many community members in one place the conversation was pretty lively. All of this relaxing was great but with a head full of ideas I&#8217;m anxious to get back to California and better tune our products based on all the feedback I received this week.</p>
<p>All of the sessions were recorded on video and I believe they&#8217;ll be made available in around a month&#8217;s time. If you can&#8217;t wait until then we have a meetup schedule for<a href="http://www.meetup.com/The-San-Francisco-ExtJS-Meetup-Group/events/17576007/"> May 23rd hosted at Sencha HQ</a> in northern California, to which you&#8217;re all invited. Just in case you&#8217;ve never been to Split before perhaps the sight that greeted us when we arrived will prompt you to get yourself on a flight.</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/05/adriatic.jpg" alt="adriatic" title="adriatic" width="660" height="493" class="aligncenter size-full wp-image-625" /></p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/05/sourcedevcon-2011-an-awesome-conference.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Proxies in Ext JS 4</title>
		<link>http://edspencer.net/2011/02/proxies-extjs-4.html</link>
		<comments>http://edspencer.net/2011/02/proxies-extjs-4.html#comments</comments>
		<pubDate>Wed, 02 Feb 2011 16:22:59 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Examples]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[reader]]></category>
		<category><![CDATA[sencha]]></category>
		<category><![CDATA[senchatouch]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=583</guid>
		<description><![CDATA[<p>One of the classes that has a lot more prominence in Ext JS 4 is the data Proxy. Proxies are responsible for all of the loading and saving of data in an Ext JS 4 or Sencha Touch application. Whenever you&#8217;re creating, updating, deleting or loading any type of data in your app, you&#8217;re almost certainly doing it via an Ext.data.Proxy.</p>
<p>If you&#8217;ve seen <a href="http://t.co/wTRxmlE">January&#8217;s Sencha newsletter</a> you may have read an article called <a href="http://www.sencha.com/blog/ext-js-4-anatomy-of-a-model/">Anatomy of a Model</a>, which introduces the most commonly-used Proxies. All a Proxy really needs is four functions &#8211; create, read, update and destroy. For an AjaxProxy, each of these will result in an Ajax request being made. For a LocalStorageProxy, the functions will create, read, update or delete records from HTML5 localStorage.</p>
<p>Because Proxies all implement the same interface they&#8217;re completely interchangeable, so you can swap out your data source &#8211; at design time or run time &#8211; without changing any other code. Although the local Proxies like LocalStorageProxy and MemoryProxy are self-contained, the remote Proxies like AjaxProxy and ScriptTagProxy make use of Readers and Writers to encode and decode their data when communicating with the server.</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/02/Proxy-Reader-and-Writer.png" alt="Proxy-Reader-and-Writer" title="Proxy-Reader-and-Writer" width="660" height="289" class="aligncenter size-full wp-image-585" /></p>
<p>Whether we are reading data from a server or preparing data to be sent back, usually we format it as either JSON or XML. Both of our frameworks come with JSON and XML Readers and Writers which handle all of this for you with a very simple API.</p>
<h3>Using a Proxy with a Model</h3>
<p>Proxies are usually used along with either a Model or a Store. The simplest setup is just with a model:</p>
<pre class="brush: jscript;">
var User = Ext.regModel('User', {
    fields: ['id', 'name', 'email'],

    proxy: {
        type: 'rest',
        url : '/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    }
});
</pre>
<p>Here we&#8217;ve created a User model with a RestProxy. RestProxy is a special form of AjaxProxy that can automatically figure out Restful urls for our models. The Proxy that we set up features a JsonReader to decode any server responses &#8211; check out the recent <a href="http://www.sencha.com/blog/2011/01/21/countdown-to-ext-js-4-data-package/">data package post</a> on the Sencha blog to see Readers in action.</p>
<p>When we use the following functions on the new User model, the Proxy is called behind the scenes:</p>
<pre class="brush: jscript;">
var user = new User({name: 'Ed Spencer'});

//CREATE: calls the RestProxy's create function because the user has never been saved
user.save();

//UPDATE: calls the RestProxy's update function because it has been saved before
user.set('email', 'ed@sencha.com');

//DESTROY: calls the RestProxy's destroy function
user.destroy();

//READ: calls the RestProxy's read function
User.load(123, {
    success: function(user) {
        console.log(user);
    }
});
</pre>
<p>We were able to perform all four CRUD operations just by specifying a Proxy for our Model. Notice that the first 3 calls are instance methods whereas the fourth (User.load) is static on the User model. Note also that you can create a Model without a Proxy, you just won&#8217;t be able to persist it.</p>
<h3>Usage with Stores</h3>
<p>In Ext JS 3.x, most of the data manipulation was done via Stores. A chief purpose of a Store is to be a local subset of some data plus delta. For example, you might have 1000 products in your database and have 25 of them loaded into a Store on the client side (the local subset). While operating on that subset, your user may have added, updated or deleted some of the Products. Until these changes are synchronized with the server they are known as a delta.</p>
<p>In order to read data from and sync to the server, Stores also need to be able to call those CRUD operations. We can give a Store a Proxy in the same way:</p>
<pre class="brush: jscript;">
var store = new Ext.data.Store({
    model: 'User',
    proxy: {
        type: 'rest',
        url : '/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    }
});
</pre>
<p>We created the exact same Proxy for the Store because that&#8217;s how our server side is set up to deliver data. Because we&#8217;ll usually want to use the same Proxy mechanism for all User manipulations, it&#8217;s usually best to just define the Proxy once on the Model and then simply tell the Store which Model to use. This automatically picks up the User model&#8217;s Proxy:</p>
<pre class="brush: jscript;">
//no need to define proxy - this will reuse the User's Proxy
var store = new Ext.data.Store({
    model: 'User'
});
</pre>
<p>Store invokes the CRUD operations via its <em>load</em> and <em>sync</em> functions. Calling load uses the Proxy&#8217;s read operation, which sync utilizes one or more of create, update and destroy depending on the current Store delta.</p>
<pre class="brush: jscript;">
//CREATE: calls the RestProxy's create function to create the Tommy record on the server
store.add({name: 'Tommy Maintz'});
store.sync();

//UPDATE: calls the RestProxy's update function to update the Tommy record on the server
store.getAt(1).set('email', 'tommy@sencha.com');
store.sync();

//DESTROY: calls the RestProxy's destroy function
store.remove(store.getAt(1));
store.sync();

//READ: calls the RestProxy's read function
store.load();
</pre>
<p>Store has used the exact same CRUD operations on the shared Proxy. In all of the examples above we have used the exact same RestProxy instance from three different places: statically on our Model (User.load), as a Model instance method (user.save, user.destroy) and via a Store instance (store.load, store.sync):</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/02/Proxy-reuse.png" alt="Proxy-reuse" title="Proxy-reuse" width="599" height="236" class="aligncenter size-full wp-image-598" /></p>
<p>Of course, most Proxies have their own private methods to do the actual work, but all a Proxy needs to do is implement those four functions to be usable with Ext JS 4 and Sencha Touch. This means it&#8217;s easy to create new Proxies, as James Pearce did in a <a href="http://www.sencha.com/learn/Tutorial:A_Sencha_Touch_MVC_application_with_PhoneGap">recent Sencha Touch example</a> where he needed to read address book data from a mobile phone. Everything he does to set up his Proxy <a href="http://www.sencha.com/learn/Tutorial:A_Sencha_Touch_MVC_application_with_PhoneGap">in the article</a> (about 1/3rd of the way down) works the same way for Ext JS 4 too.</p>
]]></description>
			<content:encoded><![CDATA[<p>One of the classes that has a lot more prominence in Ext JS 4 is the data Proxy. Proxies are responsible for all of the loading and saving of data in an Ext JS 4 or Sencha Touch application. Whenever you&#8217;re creating, updating, deleting or loading any type of data in your app, you&#8217;re almost certainly doing it via an Ext.data.Proxy.</p>
<p>If you&#8217;ve seen <a href="http://t.co/wTRxmlE">January&#8217;s Sencha newsletter</a> you may have read an article called <a href="http://www.sencha.com/blog/ext-js-4-anatomy-of-a-model/">Anatomy of a Model</a>, which introduces the most commonly-used Proxies. All a Proxy really needs is four functions &#8211; create, read, update and destroy. For an AjaxProxy, each of these will result in an Ajax request being made. For a LocalStorageProxy, the functions will create, read, update or delete records from HTML5 localStorage.</p>
<p>Because Proxies all implement the same interface they&#8217;re completely interchangeable, so you can swap out your data source &#8211; at design time or run time &#8211; without changing any other code. Although the local Proxies like LocalStorageProxy and MemoryProxy are self-contained, the remote Proxies like AjaxProxy and ScriptTagProxy make use of Readers and Writers to encode and decode their data when communicating with the server.</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/02/Proxy-Reader-and-Writer.png" alt="Proxy-Reader-and-Writer" title="Proxy-Reader-and-Writer" width="660" height="289" class="aligncenter size-full wp-image-585" /></p>
<p>Whether we are reading data from a server or preparing data to be sent back, usually we format it as either JSON or XML. Both of our frameworks come with JSON and XML Readers and Writers which handle all of this for you with a very simple API.</p>
<h3>Using a Proxy with a Model</h3>
<p>Proxies are usually used along with either a Model or a Store. The simplest setup is just with a model:</p>
<pre class="brush: jscript;">
var User = Ext.regModel('User', {
    fields: ['id', 'name', 'email'],

    proxy: {
        type: 'rest',
        url : '/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    }
});
</pre>
<p>Here we&#8217;ve created a User model with a RestProxy. RestProxy is a special form of AjaxProxy that can automatically figure out Restful urls for our models. The Proxy that we set up features a JsonReader to decode any server responses &#8211; check out the recent <a href="http://www.sencha.com/blog/2011/01/21/countdown-to-ext-js-4-data-package/">data package post</a> on the Sencha blog to see Readers in action.</p>
<p>When we use the following functions on the new User model, the Proxy is called behind the scenes:</p>
<pre class="brush: jscript;">
var user = new User({name: 'Ed Spencer'});

//CREATE: calls the RestProxy's create function because the user has never been saved
user.save();

//UPDATE: calls the RestProxy's update function because it has been saved before
user.set('email', 'ed@sencha.com');

//DESTROY: calls the RestProxy's destroy function
user.destroy();

//READ: calls the RestProxy's read function
User.load(123, {
    success: function(user) {
        console.log(user);
    }
});
</pre>
<p>We were able to perform all four CRUD operations just by specifying a Proxy for our Model. Notice that the first 3 calls are instance methods whereas the fourth (User.load) is static on the User model. Note also that you can create a Model without a Proxy, you just won&#8217;t be able to persist it.</p>
<h3>Usage with Stores</h3>
<p>In Ext JS 3.x, most of the data manipulation was done via Stores. A chief purpose of a Store is to be a local subset of some data plus delta. For example, you might have 1000 products in your database and have 25 of them loaded into a Store on the client side (the local subset). While operating on that subset, your user may have added, updated or deleted some of the Products. Until these changes are synchronized with the server they are known as a delta.</p>
<p>In order to read data from and sync to the server, Stores also need to be able to call those CRUD operations. We can give a Store a Proxy in the same way:</p>
<pre class="brush: jscript;">
var store = new Ext.data.Store({
    model: 'User',
    proxy: {
        type: 'rest',
        url : '/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    }
});
</pre>
<p>We created the exact same Proxy for the Store because that&#8217;s how our server side is set up to deliver data. Because we&#8217;ll usually want to use the same Proxy mechanism for all User manipulations, it&#8217;s usually best to just define the Proxy once on the Model and then simply tell the Store which Model to use. This automatically picks up the User model&#8217;s Proxy:</p>
<pre class="brush: jscript;">
//no need to define proxy - this will reuse the User's Proxy
var store = new Ext.data.Store({
    model: 'User'
});
</pre>
<p>Store invokes the CRUD operations via its <em>load</em> and <em>sync</em> functions. Calling load uses the Proxy&#8217;s read operation, which sync utilizes one or more of create, update and destroy depending on the current Store delta.</p>
<pre class="brush: jscript;">
//CREATE: calls the RestProxy's create function to create the Tommy record on the server
store.add({name: 'Tommy Maintz'});
store.sync();

//UPDATE: calls the RestProxy's update function to update the Tommy record on the server
store.getAt(1).set('email', 'tommy@sencha.com');
store.sync();

//DESTROY: calls the RestProxy's destroy function
store.remove(store.getAt(1));
store.sync();

//READ: calls the RestProxy's read function
store.load();
</pre>
<p>Store has used the exact same CRUD operations on the shared Proxy. In all of the examples above we have used the exact same RestProxy instance from three different places: statically on our Model (User.load), as a Model instance method (user.save, user.destroy) and via a Store instance (store.load, store.sync):</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/02/Proxy-reuse.png" alt="Proxy-reuse" title="Proxy-reuse" width="599" height="236" class="aligncenter size-full wp-image-598" /></p>
<p>Of course, most Proxies have their own private methods to do the actual work, but all a Proxy needs to do is implement those four functions to be usable with Ext JS 4 and Sencha Touch. This means it&#8217;s easy to create new Proxies, as James Pearce did in a <a href="http://www.sencha.com/learn/Tutorial:A_Sencha_Touch_MVC_application_with_PhoneGap">recent Sencha Touch example</a> where he needed to read address book data from a mobile phone. Everything he does to set up his Proxy <a href="http://www.sencha.com/learn/Tutorial:A_Sencha_Touch_MVC_application_with_PhoneGap">in the article</a> (about 1/3rd of the way down) works the same way for Ext JS 4 too.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/02/proxies-extjs-4.html/feed</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>Introduction to Ext JS 4</title>
		<link>http://edspencer.net/2011/01/introducing-ext-js-4.html</link>
		<comments>http://edspencer.net/2011/01/introducing-ext-js-4.html#comments</comments>
		<pubDate>Thu, 27 Jan 2011 16:30:20 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[extjs4]]></category>
		<category><![CDATA[senchacon]]></category>
		<category><![CDATA[talk]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=566</guid>
		<description><![CDATA[<p>At the end of last 2010 we capped off an incredible year with SenchaCon &#8211; by far the biggest gathering of Sencha developers ever assembled. We descended on San Francisco, 500 strong, and spent an amazing few days sharing the awesome new stuff we&#8217;re working on, learning from each other, and addressing the web&#8217;s most pressing problems.</p>
<p>Now, we&#8217;re proud to release <a href="http://www.sencha.com/conference/sessions/videos.php">all of the videos</a> from the conference completely free for everyone. You can see a <a href="http://www.sencha.com/conference/sessions/videos.php">full list</a> on our conference site, where you&#8217;ll find days worth of material all about Ext JS 4, Sencha Touch and all of the other treats we&#8217;re working on at the moment. </p>
<p>Some of the videos in particular stand out for me &#8211; Jamie&#8217;s <a href="http://vimeo.com/17673342">Charting</a> and <a href="http://vimeo.com/17917111">Layouts</a> talks were spectacular, as was Rob&#8217;s <a href="http://vimeo.com/19159630">Theming Ext JS 4</a> talk. On the Touch side, Tommy&#8217;s talks on <a href="http://vimeo.com/17699976">Performance</a> and <a href="http://vimeo.com/17853133">Debugging</a> are required viewing, as is Dave Kaneda&#8217;s characteristically off the cuff <a href="http://vimeo.com/17705448">Theming</a> talk.</p>
<p>My personal high point was standing in front of all of you and introducing Ext JS 4 and its three core goals &#8211; speed, stability and ease of use. I think you&#8217;re going to love what we&#8217;ve done with the framework in version 4, but for now I&#8217;ll let the video do the talking:</p>
<p><iframe src="http://player.vimeo.com/video/17666102" width="650" height="380" frameborder="0"></iframe></p>
<p>If you&#8217;re so inclined, you can find the <a href="http://www.slideshare.net/edspencer/intro-to-ext-4">slides for this talk</a> on slideshare, and if you can still stand the sound of my voice check out my other presentation on <a href="http://vimeo.com/17733892">Ext JS 4 Architecture</a>, focusing chiefly on the new data package (<a href="http://www.slideshare.net/edspencer/ext-js-4-architecture">slides</a>).</p>
]]></description>
			<content:encoded><![CDATA[<p>At the end of last 2010 we capped off an incredible year with SenchaCon &#8211; by far the biggest gathering of Sencha developers ever assembled. We descended on San Francisco, 500 strong, and spent an amazing few days sharing the awesome new stuff we&#8217;re working on, learning from each other, and addressing the web&#8217;s most pressing problems.</p>
<p>Now, we&#8217;re proud to release <a href="http://www.sencha.com/conference/sessions/videos.php">all of the videos</a> from the conference completely free for everyone. You can see a <a href="http://www.sencha.com/conference/sessions/videos.php">full list</a> on our conference site, where you&#8217;ll find days worth of material all about Ext JS 4, Sencha Touch and all of the other treats we&#8217;re working on at the moment. </p>
<p>Some of the videos in particular stand out for me &#8211; Jamie&#8217;s <a href="http://vimeo.com/17673342">Charting</a> and <a href="http://vimeo.com/17917111">Layouts</a> talks were spectacular, as was Rob&#8217;s <a href="http://vimeo.com/19159630">Theming Ext JS 4</a> talk. On the Touch side, Tommy&#8217;s talks on <a href="http://vimeo.com/17699976">Performance</a> and <a href="http://vimeo.com/17853133">Debugging</a> are required viewing, as is Dave Kaneda&#8217;s characteristically off the cuff <a href="http://vimeo.com/17705448">Theming</a> talk.</p>
<p>My personal high point was standing in front of all of you and introducing Ext JS 4 and its three core goals &#8211; speed, stability and ease of use. I think you&#8217;re going to love what we&#8217;ve done with the framework in version 4, but for now I&#8217;ll let the video do the talking:</p>
<p><iframe src="http://player.vimeo.com/video/17666102" width="650" height="380" frameborder="0"></iframe></p>
<p>If you&#8217;re so inclined, you can find the <a href="http://www.slideshare.net/edspencer/intro-to-ext-4">slides for this talk</a> on slideshare, and if you can still stand the sound of my voice check out my other presentation on <a href="http://vimeo.com/17733892">Ext JS 4 Architecture</a>, focusing chiefly on the new data package (<a href="http://www.slideshare.net/edspencer/ext-js-4-architecture">slides</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/01/introducing-ext-js-4.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Ext JS 4: The Class Definition Pipeline</title>
		<link>http://edspencer.net/2011/01/ext-js-4-the-class-definition-pipeline.html</link>
		<comments>http://edspencer.net/2011/01/ext-js-4-the-class-definition-pipeline.html#comments</comments>
		<pubDate>Tue, 25 Jan 2011 16:25:00 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Examples]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[classes]]></category>
		<category><![CDATA[extjs4]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=538</guid>
		<description><![CDATA[<p>Last time, we looked at some of the features of the <a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">new class system in Ext JS 4</a>, and explored some of the code that makes it work. Today we&#8217;re going to dig a little deeper and look at the class definition pipeline &#8211; the framework responsible for creating every class in Ext JS 4.</p>
<p><a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">As I mentioned last time</a>, every class in Ext JS 4 is an instance of Ext.Class. When an Ext.Class is constructed, it hands itself off to a pipeline populated by small, focused processors, each of which handles one part of the class definition process. We ship a number of these processors out of the box &#8211; there are processors for handling mixins, setting up configuration functions and handling class extension.</p>
<p>The pipeline is probably best explained with a picture. Think of your class starting its definition journey at the bottom left, working its way up the preprocessors on the left hand side and then down the postprocessors on the right, until finally it reaches the end, where it signals its readiness to a callback function:</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/01/Processors.png" alt="Ext JS 4 Class Definition Pipeline" title="Ext JS 4 Class Definition Pipeline" width="687" height="537" class="aligncenter size-full wp-image-528" /></p>
<p>The distinction between preprocessors and postprocessors is that a class is considered ‘ready’ (e.g. can be instantiated) after the preprocessors have all been executed. Postprocessors typically perform functions like aliasing the class name to an xtype or back to a legacy class name &#8211; things that don&#8217;t affect the class&#8217; behavior.</p>
<p>Each processor runs asynchronously, calling back to the Ext.Class constructor when it is ready &#8211; this is what enables us to extend classes that don’t exist on the page yet. The first preprocessor is the Loader, which checks to see if all of the new Class’ dependencies are available. If they are not, the Loader can dynamically load those dependencies before calling back to Ext.Class and allowing the next preprocessor to run. We&#8217;ll take another look at the Loader in another post.</p>
<p>After running the Loader, the new Class is set up to inherit from the declared superclass by the Extend preprocessor. The Mixins preprocessor takes care of copying all of the functions from each of our mixins, and the Config preprocessor handles the creation of the 4 config functions we saw last time (e.g. getTitle, setTitle, resetTitle, applyTitle &#8211; check out <a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">yesterday&#8217;s post</a> to see how the Configs processor helps out).</p>
<p>Finally, the Statics preprocessor looks for any static functions that we set up on our new class and makes them available statically on the class. The processors that are run are completely customizable, and it’s easy to add custom processors at any point. Let&#8217;s take a look at that Statics preprocessor as an example:</p>
<pre class="brush: jscript;">
//Each processor is passed three arguments - the class under construction,
//the configuration for that class and a callback function to call when the processor has finished
Ext.Class.registerPreprocessor('statics', function(cls, data, callback) {
    if (Ext.isObject(data.statics)) {
        var statics = data.statics,
            name;

        //here we just copy each static function onto the new Class
        for (name in statics) {
            if (statics.hasOwnProperty(name)) {
                cls[name] = statics[name];
            }
        }
    }

    delete data.statics;

    //Once the processor's work is done, we just call the callback function to kick off the next processor
    if (callback) {
        callback.call(this, cls, data);
    }
});

//Changing the order that the preprocessors are called in is easy too - this is the default
Ext.Class.setDefaultPreprocessors(['extend', 'mixins', 'config', 'statics']);
</pre>
<p>What happens above is pretty straightforward. We&#8217;re registering a preprocessor called &#8217;statics&#8217; with Ext.Class. The function we provide is called whenever the &#8217;statics&#8217; preprocessor is invoked, and is passed the new Ext.Class instance, the configuration for that class, and a callback to call when the preprocessor has finished its work.</p>
<p>The actual work that this preprocessor does is trivial &#8211; it just looks to see if we declared a &#8217;statics&#8217; property in our class configuration and if so copies it onto the new class. For example, let&#8217;s say we want to create a static getNextId function on a class:</p>
<pre class="brush: jscript;">
Ext.define('MyClass', {
    statics: {
        idSeed: 1000,
        getNextId: function() {
            return this.idSeed++;
        }
    }
});
</pre>
<p>Because of the Statics preprocessor, we can now call the function statically on the Class (e.g. without creating an instance of MyClass):</p>
<pre class="brush: jscript;">
MyClass.getNextId(); //1000
MyClass.getNextId(); //1001
MyClass.getNextId(); //1002
... etc
</pre>
<p>Finally, let&#8217;s come back to that callback at the bottom of the picture above. If we supply one, a callback function is run after all of the processors have run. At this point the new class is completely ready for use in your application. Here we create an instance of MyClass using the callback function, guaranteeing that the dependency on Ext.Window has been honored:</p>
<pre class="brush: jscript;">
Ext.define('MyClass', {
    extend: 'Ext.Window'
}, function() {
   //this callback is called when MyClass is ready for use
   var cls = new MyClass();
   cls.setTitle('Everything is ready');
   cls.show();
});
</pre>
<p>That&#8217;s it for today. Next time we&#8217;ll look at some of the new features in the part of Ext JS 4 that is closest to my heart &#8211; the data package.</p>
]]></description>
			<content:encoded><![CDATA[<p>Last time, we looked at some of the features of the <a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">new class system in Ext JS 4</a>, and explored some of the code that makes it work. Today we&#8217;re going to dig a little deeper and look at the class definition pipeline &#8211; the framework responsible for creating every class in Ext JS 4.</p>
<p><a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">As I mentioned last time</a>, every class in Ext JS 4 is an instance of Ext.Class. When an Ext.Class is constructed, it hands itself off to a pipeline populated by small, focused processors, each of which handles one part of the class definition process. We ship a number of these processors out of the box &#8211; there are processors for handling mixins, setting up configuration functions and handling class extension.</p>
<p>The pipeline is probably best explained with a picture. Think of your class starting its definition journey at the bottom left, working its way up the preprocessors on the left hand side and then down the postprocessors on the right, until finally it reaches the end, where it signals its readiness to a callback function:</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/01/Processors.png" alt="Ext JS 4 Class Definition Pipeline" title="Ext JS 4 Class Definition Pipeline" width="687" height="537" class="aligncenter size-full wp-image-528" /></p>
<p>The distinction between preprocessors and postprocessors is that a class is considered ‘ready’ (e.g. can be instantiated) after the preprocessors have all been executed. Postprocessors typically perform functions like aliasing the class name to an xtype or back to a legacy class name &#8211; things that don&#8217;t affect the class&#8217; behavior.</p>
<p>Each processor runs asynchronously, calling back to the Ext.Class constructor when it is ready &#8211; this is what enables us to extend classes that don’t exist on the page yet. The first preprocessor is the Loader, which checks to see if all of the new Class’ dependencies are available. If they are not, the Loader can dynamically load those dependencies before calling back to Ext.Class and allowing the next preprocessor to run. We&#8217;ll take another look at the Loader in another post.</p>
<p>After running the Loader, the new Class is set up to inherit from the declared superclass by the Extend preprocessor. The Mixins preprocessor takes care of copying all of the functions from each of our mixins, and the Config preprocessor handles the creation of the 4 config functions we saw last time (e.g. getTitle, setTitle, resetTitle, applyTitle &#8211; check out <a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">yesterday&#8217;s post</a> to see how the Configs processor helps out).</p>
<p>Finally, the Statics preprocessor looks for any static functions that we set up on our new class and makes them available statically on the class. The processors that are run are completely customizable, and it’s easy to add custom processors at any point. Let&#8217;s take a look at that Statics preprocessor as an example:</p>
<pre class="brush: jscript;">
//Each processor is passed three arguments - the class under construction,
//the configuration for that class and a callback function to call when the processor has finished
Ext.Class.registerPreprocessor('statics', function(cls, data, callback) {
    if (Ext.isObject(data.statics)) {
        var statics = data.statics,
            name;

        //here we just copy each static function onto the new Class
        for (name in statics) {
            if (statics.hasOwnProperty(name)) {
                cls[name] = statics[name];
            }
        }
    }

    delete data.statics;

    //Once the processor's work is done, we just call the callback function to kick off the next processor
    if (callback) {
        callback.call(this, cls, data);
    }
});

//Changing the order that the preprocessors are called in is easy too - this is the default
Ext.Class.setDefaultPreprocessors(['extend', 'mixins', 'config', 'statics']);
</pre>
<p>What happens above is pretty straightforward. We&#8217;re registering a preprocessor called &#8217;statics&#8217; with Ext.Class. The function we provide is called whenever the &#8217;statics&#8217; preprocessor is invoked, and is passed the new Ext.Class instance, the configuration for that class, and a callback to call when the preprocessor has finished its work.</p>
<p>The actual work that this preprocessor does is trivial &#8211; it just looks to see if we declared a &#8217;statics&#8217; property in our class configuration and if so copies it onto the new class. For example, let&#8217;s say we want to create a static getNextId function on a class:</p>
<pre class="brush: jscript;">
Ext.define('MyClass', {
    statics: {
        idSeed: 1000,
        getNextId: function() {
            return this.idSeed++;
        }
    }
});
</pre>
<p>Because of the Statics preprocessor, we can now call the function statically on the Class (e.g. without creating an instance of MyClass):</p>
<pre class="brush: jscript;">
MyClass.getNextId(); //1000
MyClass.getNextId(); //1001
MyClass.getNextId(); //1002
... etc
</pre>
<p>Finally, let&#8217;s come back to that callback at the bottom of the picture above. If we supply one, a callback function is run after all of the processors have run. At this point the new class is completely ready for use in your application. Here we create an instance of MyClass using the callback function, guaranteeing that the dependency on Ext.Window has been honored:</p>
<pre class="brush: jscript;">
Ext.define('MyClass', {
    extend: 'Ext.Window'
}, function() {
   //this callback is called when MyClass is ready for use
   var cls = new MyClass();
   cls.setTitle('Everything is ready');
   cls.show();
});
</pre>
<p>That&#8217;s it for today. Next time we&#8217;ll look at some of the new features in the part of Ext JS 4 that is closest to my heart &#8211; the data package.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/01/ext-js-4-the-class-definition-pipeline.html/feed</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Classes in Ext JS 4: Under the hood</title>
		<link>http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html</link>
		<comments>http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html#comments</comments>
		<pubDate>Mon, 24 Jan 2011 16:37:22 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[classes]]></category>
		<category><![CDATA[dynamic loading]]></category>
		<category><![CDATA[extjs4]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=518</guid>
		<description><![CDATA[<p>Last week we unveiled a the brand new class system coming in Ext JS 4. If you haven’t seen the new system in action I hope you’ll take a look at the <a href="http://www.sencha.com/blog/2011/01/19/countdown-to-ext-js-4-dynamic-loading-and-new-class-system/">blog post</a> on sencha.com and check out the <a href="http://dev.sencha.com/deploy/LoaderDemo/">live demo</a>. Today we’re going to dig a little deeper into the class system to see how it actually works.</p>
<p>To briefly recap, the new class system enables us to define classes like this:</p>
<pre class="brush: jscript;">
Ext.define('Ext.Window', {
    extend: 'Ext.Panel',
    requires: 'Ext.Tool',
    mixins: {
        draggable: 'Ext.util.Draggable'
    },

    config: {
        title: &quot;Window Title&quot;
    }
});
</pre>
<p>Here we’ve set up a slightly simplified version of the Ext.Window class. We’ve set Window up to be a subclass of Panel, declared that it requires the Ext.Tool class and that it mixes in functionality from the Ext.util.Draggable class.</p>
<p>There are a few new things here so we’ll attack them one at a time. The ‘extend’ declaration does what you’d expect &#8211; we’re just saying that Window should be a subclass of Panel. The ‘requires’ declaration means that the named classes (just Ext.Tool in this case) have to be present before the Window class can be considered ‘ready’ for use (more on class readiness in a moment).</p>
<p>The ‘mixins’ declaration is a brand new concept when it comes to Ext JS. A mixin is just a set of functions (and sometimes properties) that are merged into a class. For example, the Ext.util.Draggable mixin we defined above might contain a function called ‘startDragging’ &#8211; this gets copied into Ext.Window to enable us to use the function in a window instance:</p>
<pre class="brush: jscript;">
//a simplified Draggable mixin
Ext.define('Ext.util.Draggable', {
    startDragging: function() {
        console.log('started dragging');
    }
});
</pre>
<p>When we create a new Ext.Window instance now, we can call the function that was mixed in from Ext.util.Draggable:</p>
<pre class="brush: jscript;">
var win = Ext.create('Ext.Window');
win.startDragging(); //&quot;started dragging&quot;
</pre>
<p>Mixins are really useful when a class needs to inherit multiple traits but can’t do so easily using a traditional single inheritance mechanism. For example, Ext.Windows is a draggable component, as are Sliders, Grid headers, and many other UI elements. Because this behavior crops up in many different places it’s not feasible to work the draggable behavior into a single superclass because not all of those UI elements actually share a common superclass. Creating a Draggable mixin solves this problem &#8211; now anything can be made draggable with a couple of lines of code.</p>
<p>The last new piece of functionality I’ll mention briefly is the ‘config’ declaration. Most of the classes in Ext JS take configuration parameters, many of which can be changed at runtime. In the Ext.Window above example we declared that the class has a ‘title’ configuration, which takes the default value of ‘Window Title’. By setting the class up like this we get 4 methods for free &#8211; getTitle, setTitle, resetTitle and applyTitle.</p>
<ul>
<li><b>getTitle</b> &#8211; returns the current title</li>
<li><b>setTitle</b> &#8211; sets the title to a new value</li>
<li><b>resetTitle</b> &#8211;  reverts the title to its default value (‘Window Title’)</li>
<li><b>applyTitle</b> &#8211; this is a template method that you can choose to define. It is called whenever setTitle is called.
</ul>
<p>The applyTitle function is the place to put any logic that needs to be called when the title is changed &#8211; for example we might want to update a DOM Element with the new title:</p>
<pre class="brush: jscript;">
Ext.define(‘Ext.Window’, {
    //..as above,

    config: {
        title: 'Window Title'
    },

    //updates the DOM element that contains the window title
    applyTitle: function(newTitle) {
        this.titleEl.update(newTitle);
    }
});
</pre>
<p>This saves us a lot of time and code while providing a consistent API for all configuration options: win-win.</p>
<h3>Digging Deeper</h3>
<p>Ext JS 4 introduces 4 new classes to make all this magic work:</p>
<ul>
<li><b>Ext.Base</b> &#8211; all classes inherit from Ext.Base. It provides basic low-level functionality used by all classes</li>
<li><b>Ext.Class</b> &#8211; a factory for making new classes</li>
<li><b>Ext.ClassLoader</b> &#8211; responsible for ensuring that classes are available, loading them if they aren’t on the page already</li>
<li><b>Ext.ClassManager</b> &#8211; kicks off class creation and manages dependencies</li>
</ul>
<p>These all work together behind the scenes and most of the time you won’t even need to be aware of what is being called when you define and use a class. The two functions that you’ll use most often &#8211; Ext.define and Ext.create &#8211; both call Ext.ClassManager under the hood, which in turn utilizes the other three classes to put everything together.</p>
<p>The distinction between Ext.Class and Ext.Base is important. Ext.Base is the top-level <i>superclass</i> for every class ever defined &#8211; every class inherits from Ext.Base at some point. Ext.Class represents the class itself &#8211; every class you define is an <i>instance</i> of Ext.Class, and a <i>subclass</i> of Ext.Base. To illustrate, let’s say we created a class called MyClass, which doesn’t extend any other class:</p>
<pre class="brush: jscript;">
Ext.define('MyClass', {
    someFunction: function() {
        console.log('Ran some function');
    }
});
</pre>
<p>The direct superclass for MyClass is Ext.Base because we didn’t specify that MyClass should extend anything else. If you imagine a tree of all the classes we’ve defined so far, it will look something like this:</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/01/Sample-inheritance-tree.png" alt="Sample-inheritance-tree" title="Sample-inheritance-tree" width="435" height="398" class="aligncenter size-full wp-image-522" /></p>
<p>This tree bases its hierarchy on the inheritance structure of our classes, and the root is always Ext.Base &#8211; that is, every class eventually inherits from Ext.Base. So every item in the diagram above is a <i>subclass</i> of Ext.Base, but every item is also an <i>instance</i> of Ext.Class. Classes themselves are instances of Ext.Class, which means we can easily modify the Class at a later time &#8211; for example mixing in additional functionality:</p>
<pre class="brush: jscript;">
//we can define some mixins at definition time
Ext.define('MyClass', {
    mixins: {
        observable: 'Ext.util.Observable'
    }
});

//it’s easy to add more later too
MyClass.mixin('draggable', 'Ext.util.Draggable');
</pre>
<p>This architecture opens up new possibilities for dynamic class creation and metaprogramming, which were difficult to pull off in earlier versions.</p>
<p>In the next episode, we’ll look at how the class definition pipeline is structured and how to extend it to add your own features.</p>
]]></description>
			<content:encoded><![CDATA[<p>Last week we unveiled a the brand new class system coming in Ext JS 4. If you haven’t seen the new system in action I hope you’ll take a look at the <a href="http://www.sencha.com/blog/2011/01/19/countdown-to-ext-js-4-dynamic-loading-and-new-class-system/">blog post</a> on sencha.com and check out the <a href="http://dev.sencha.com/deploy/LoaderDemo/">live demo</a>. Today we’re going to dig a little deeper into the class system to see how it actually works.</p>
<p>To briefly recap, the new class system enables us to define classes like this:</p>
<pre class="brush: jscript;">
Ext.define('Ext.Window', {
    extend: 'Ext.Panel',
    requires: 'Ext.Tool',
    mixins: {
        draggable: 'Ext.util.Draggable'
    },

    config: {
        title: &quot;Window Title&quot;
    }
});
</pre>
<p>Here we’ve set up a slightly simplified version of the Ext.Window class. We’ve set Window up to be a subclass of Panel, declared that it requires the Ext.Tool class and that it mixes in functionality from the Ext.util.Draggable class.</p>
<p>There are a few new things here so we’ll attack them one at a time. The ‘extend’ declaration does what you’d expect &#8211; we’re just saying that Window should be a subclass of Panel. The ‘requires’ declaration means that the named classes (just Ext.Tool in this case) have to be present before the Window class can be considered ‘ready’ for use (more on class readiness in a moment).</p>
<p>The ‘mixins’ declaration is a brand new concept when it comes to Ext JS. A mixin is just a set of functions (and sometimes properties) that are merged into a class. For example, the Ext.util.Draggable mixin we defined above might contain a function called ‘startDragging’ &#8211; this gets copied into Ext.Window to enable us to use the function in a window instance:</p>
<pre class="brush: jscript;">
//a simplified Draggable mixin
Ext.define('Ext.util.Draggable', {
    startDragging: function() {
        console.log('started dragging');
    }
});
</pre>
<p>When we create a new Ext.Window instance now, we can call the function that was mixed in from Ext.util.Draggable:</p>
<pre class="brush: jscript;">
var win = Ext.create('Ext.Window');
win.startDragging(); //&quot;started dragging&quot;
</pre>
<p>Mixins are really useful when a class needs to inherit multiple traits but can’t do so easily using a traditional single inheritance mechanism. For example, Ext.Windows is a draggable component, as are Sliders, Grid headers, and many other UI elements. Because this behavior crops up in many different places it’s not feasible to work the draggable behavior into a single superclass because not all of those UI elements actually share a common superclass. Creating a Draggable mixin solves this problem &#8211; now anything can be made draggable with a couple of lines of code.</p>
<p>The last new piece of functionality I’ll mention briefly is the ‘config’ declaration. Most of the classes in Ext JS take configuration parameters, many of which can be changed at runtime. In the Ext.Window above example we declared that the class has a ‘title’ configuration, which takes the default value of ‘Window Title’. By setting the class up like this we get 4 methods for free &#8211; getTitle, setTitle, resetTitle and applyTitle.</p>
<ul>
<li><b>getTitle</b> &#8211; returns the current title</li>
<li><b>setTitle</b> &#8211; sets the title to a new value</li>
<li><b>resetTitle</b> &#8211;  reverts the title to its default value (‘Window Title’)</li>
<li><b>applyTitle</b> &#8211; this is a template method that you can choose to define. It is called whenever setTitle is called.
</ul>
<p>The applyTitle function is the place to put any logic that needs to be called when the title is changed &#8211; for example we might want to update a DOM Element with the new title:</p>
<pre class="brush: jscript;">
Ext.define(‘Ext.Window’, {
    //..as above,

    config: {
        title: 'Window Title'
    },

    //updates the DOM element that contains the window title
    applyTitle: function(newTitle) {
        this.titleEl.update(newTitle);
    }
});
</pre>
<p>This saves us a lot of time and code while providing a consistent API for all configuration options: win-win.</p>
<h3>Digging Deeper</h3>
<p>Ext JS 4 introduces 4 new classes to make all this magic work:</p>
<ul>
<li><b>Ext.Base</b> &#8211; all classes inherit from Ext.Base. It provides basic low-level functionality used by all classes</li>
<li><b>Ext.Class</b> &#8211; a factory for making new classes</li>
<li><b>Ext.ClassLoader</b> &#8211; responsible for ensuring that classes are available, loading them if they aren’t on the page already</li>
<li><b>Ext.ClassManager</b> &#8211; kicks off class creation and manages dependencies</li>
</ul>
<p>These all work together behind the scenes and most of the time you won’t even need to be aware of what is being called when you define and use a class. The two functions that you’ll use most often &#8211; Ext.define and Ext.create &#8211; both call Ext.ClassManager under the hood, which in turn utilizes the other three classes to put everything together.</p>
<p>The distinction between Ext.Class and Ext.Base is important. Ext.Base is the top-level <i>superclass</i> for every class ever defined &#8211; every class inherits from Ext.Base at some point. Ext.Class represents the class itself &#8211; every class you define is an <i>instance</i> of Ext.Class, and a <i>subclass</i> of Ext.Base. To illustrate, let’s say we created a class called MyClass, which doesn’t extend any other class:</p>
<pre class="brush: jscript;">
Ext.define('MyClass', {
    someFunction: function() {
        console.log('Ran some function');
    }
});
</pre>
<p>The direct superclass for MyClass is Ext.Base because we didn’t specify that MyClass should extend anything else. If you imagine a tree of all the classes we’ve defined so far, it will look something like this:</p>
<p><img src="http://edspencer.net/wp-content/uploads/2011/01/Sample-inheritance-tree.png" alt="Sample-inheritance-tree" title="Sample-inheritance-tree" width="435" height="398" class="aligncenter size-full wp-image-522" /></p>
<p>This tree bases its hierarchy on the inheritance structure of our classes, and the root is always Ext.Base &#8211; that is, every class eventually inherits from Ext.Base. So every item in the diagram above is a <i>subclass</i> of Ext.Base, but every item is also an <i>instance</i> of Ext.Class. Classes themselves are instances of Ext.Class, which means we can easily modify the Class at a later time &#8211; for example mixing in additional functionality:</p>
<pre class="brush: jscript;">
//we can define some mixins at definition time
Ext.define('MyClass', {
    mixins: {
        observable: 'Ext.util.Observable'
    }
});

//it’s easy to add more later too
MyClass.mixin('draggable', 'Ext.util.Draggable');
</pre>
<p>This architecture opens up new possibilities for dynamic class creation and metaprogramming, which were difficult to pull off in earlier versions.</p>
<p>In the next episode, we’ll look at how the class definition pipeline is structured and how to extend it to add your own features.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html/feed</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Sencha Touch tech talk at Pivotal Labs</title>
		<link>http://edspencer.net/2010/09/sencha-touch-tech-talk-at-pivotal-labs.html</link>
		<comments>http://edspencer.net/2010/09/sencha-touch-tech-talk-at-pivotal-labs.html#comments</comments>
		<pubDate>Mon, 27 Sep 2010 19:46:58 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Examples]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=489</guid>
		<description><![CDATA[<p>I recently gave an <a href="http://pivotallabs.com/talks/109-sencha-touch">introduction to Sencha Touch</a> talk up at Pivotal Labs in San Francisco. The guys at Pivotal were kind enough to record this short talk and share it with the world &#8211; it&#8217;s under 30 minutes and serves as a nice, short introduction to Sencha Touch:</p>
<p><a href="http://pivotallabs.com/talks/109-sencha-touch"><img src="http://edspencer.net/wp-content/uploads/2010/09/Screen-shot-2010-09-27-at-11.53.54-AM.png" alt="Ed Spencer Sencha Touch tech talk" title="Ed Spencer Sencha Touch tech talk" width="480" height="294" class="aligncenter size-full wp-image-502" /></a></p>
<p>The slides are available on slideshare and include the code snippets I presented. The Dribbble example used in the talk is very similar to the <a href="http://kivamobile.org/">Kiva example</a> that ships with the <a href="http://www.sencha.com/products/touch/">Sencha Touch SDK</a>, so I recommend checking that out if you want to dive in further.</p>
<div style="margin-left: 115px; width:425px" id="__ss_5176823"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/edspencer/introduction-to-sencha-touch" title="Introduction to Sencha Touch">Introduction to Sencha Touch</a></strong><object id="__sse5176823" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=2010-100910201826-phpapp01&#038;stripped_title=introduction-to-sencha-touch&#038;userName=edspencer" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5176823" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=2010-100910201826-phpapp01&#038;stripped_title=introduction-to-sencha-touch&#038;userName=edspencer" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/edspencer">Ed Spencer</a>.</div>
</div>
]]></description>
			<content:encoded><![CDATA[<p>I recently gave an <a href="http://pivotallabs.com/talks/109-sencha-touch">introduction to Sencha Touch</a> talk up at Pivotal Labs in San Francisco. The guys at Pivotal were kind enough to record this short talk and share it with the world &#8211; it&#8217;s under 30 minutes and serves as a nice, short introduction to Sencha Touch:</p>
<p><a href="http://pivotallabs.com/talks/109-sencha-touch"><img src="http://edspencer.net/wp-content/uploads/2010/09/Screen-shot-2010-09-27-at-11.53.54-AM.png" alt="Ed Spencer Sencha Touch tech talk" title="Ed Spencer Sencha Touch tech talk" width="480" height="294" class="aligncenter size-full wp-image-502" /></a></p>
<p>The slides are available on slideshare and include the code snippets I presented. The Dribbble example used in the talk is very similar to the <a href="http://kivamobile.org/">Kiva example</a> that ships with the <a href="http://www.sencha.com/products/touch/">Sencha Touch SDK</a>, so I recommend checking that out if you want to dive in further.</p>
<div style="margin-left: 115px; width:425px" id="__ss_5176823"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/edspencer/introduction-to-sencha-touch" title="Introduction to Sencha Touch">Introduction to Sencha Touch</a></strong><object id="__sse5176823" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=2010-100910201826-phpapp01&#038;stripped_title=introduction-to-sencha-touch&#038;userName=edspencer" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5176823" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=2010-100910201826-phpapp01&#038;stripped_title=introduction-to-sencha-touch&#038;userName=edspencer" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/edspencer">Ed Spencer</a>.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2010/09/sencha-touch-tech-talk-at-pivotal-labs.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using the Ext JS PivotGrid</title>
		<link>http://edspencer.net/2010/07/using-the-ext-js-pivotgrid.html</link>
		<comments>http://edspencer.net/2010/07/using-the-ext-js-pivotgrid.html#comments</comments>
		<pubDate>Thu, 29 Jul 2010 19:10:13 +0000</pubDate>
		<dc:creator>Ed Spencer</dc:creator>
				<category><![CDATA[Examples]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[3.3]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[grid]]></category>
		<category><![CDATA[pivotgrid]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[stores]]></category>

		<guid isPermaLink="false">http://edspencer.net/?p=479</guid>
		<description><![CDATA[<p>One of the new components we just unveiled for the <a href="http://www.sencha.com/blog/2010/07/28/announcing-ext-js-3-3-beta-pivotgrids-calendars-and-more/">Ext JS 3.3 beta</a> is PivotGrid. PivotGrid is a powerful new component that reduces and aggregates large datasets into a more understandable form.</p>
<p>A classic example of PivotGrid&#8217;s usefulness is in analyzing sales data. Companies often keep a database containing all the sales they have made and want to glean some insight into how well they are performing. PivotGrid gives the ability to rapidly summarize this large and unwieldy dataset &#8211; for example showing sales count broken down by city and salesperson.</p>
<h2>A simple example</h2>
<p>We created <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/simple.html">an example of this scenario</a> in the 3.3 beta release. Here we have a fictional dataset containing 300 rows of sales data (<a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/simple.json">see the raw data</a>). We asked PivotGrid to break the data down by Salesperson and Product, showing us how they performed over time. Each cell contains the sum of sales made by the given salesperson/product combination in the given city and year.</p>
<p>Let&#8217;s see how we create this PivotGrid:</p>
<pre class="brush: jscript;">
var SaleRecord = Ext.data.Record.create([
    {name: 'person',   type: 'string'},
    {name: 'product',  type: 'string'},
    {name: 'city',     type: 'string'},
    {name: 'state',    type: 'string'},
    {name: 'month',    type: 'int'},
    {name: 'quarter',  type: 'int'},
    {name: 'year',     type: 'int'},
    {name: 'quantity', type: 'int'},
    {name: 'value',    type: 'int'}
]);

var myStore = new Ext.data.Store({
    url: 'salesdata.json',
    autoLoad: true,
    reader: new Ext.data.JsonReader({
        root: 'rows',
        idProperty: 'id'
    }, SaleRecord)
});

var pivotGrid = new Ext.grid.PivotGrid({
    title     : 'Sales Performance',
    store     : myStore,
    aggregator: 'sum',
    measure   : 'value',

    leftAxis: [
        {dataIndex: 'person',  width: 80},
        {dataIndex: 'product', width: 90}
    ],

    topAxis: [
        {dataIndex: 'year'},
        {dataIndex: 'city'}
    ]
});
</pre>
<p>The first half of this ought to be very familiar &#8211; we just set up a normal Record and Store. This is all we need to load our <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/simple.json">sample data</a> so that it&#8217;s ready for pivoting. This is all exactly the same code as for our other Store-bound components like Grid and DataView so it&#8217;s easy to take an existing Grid and turn it into a PivotGrid.</p>
<p>The second half of the code creates the PivotGrid itself. There are 5 main components to a PivotGrid &#8211; the store, the measure, the aggregator, the left axis and the top axis. Taking these in turn:</p>
<ul>
<li><b>Store</b> &#8211; the Store we created above</li>
<li><b>Measure</b> &#8211; the field in the data that we want to aggregate (in this case the sale value)</li>
<li><b>Aggregator</b> &#8211; the function we use to combine data into the cells. <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/docs/?class=Ext.grid.PivotGrid">See the docs</a> for full details</li>
<li><b>Left Axis</b> &#8211; the fields to break data down by on the left axis</li>
<li><b>Top Axis</b> &#8211; the fields to break data down by on the top axis</li>
</ul>
<p>The measure and the items in the axes must all be fields from the Store. The aggregator function can usually be passed in as a string &#8211; there are 5 aggregator functions built in: sum, count, min, max and avg.</p>
<h2>Renderers</h2>
<p>This is all we need to create a simple PivotGrid; now it&#8217;s time to look at a few more advanced options. Let&#8217;s start with renderers. Once the data for each cell has been calculated, the value is passed to an optional renderer function, which takes each value in turn and returns another value. <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/people.html">One of the PivotGrid examples</a> shows average heights in feet and inches but the calculated data is in decimal. Here&#8217;s the renderer we use in that example:</p>
<pre class="brush: jscript;">
new Ext.grid.PivotGrid({
    store     : myStore,
    aggregator: 'avg',
    measure   : 'height',

    //turns a decimal number of feet into feet and inches
    renderer  : function(value) {
        var feet   = Math.floor(value),
            inches = Math.round((value - feet) * 12);

        return String.format(&quot;{0}' {1}\&quot;&quot;, feet, inches);
    },
    //the rest of the config
});
</pre>
<h2>Customising cell appearance</h2>
<p>Another one of the <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/countries.html">PivotGrid examples uses a custom cell style</a>. As with the renderer, each cell has the opportunity to alter itself with a custom function &#8211; here&#8217;s the one we use in the <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/countries.html">countries example</a>:</p>
<pre class="brush: jscript;">
new Ext.grid.PivotGrid({
    store     : myStore,
    aggregator: 'avg',
    measure   : 'height',

    viewConfig: {
        getCellCls: function(value) {
            if (value &lt; 20) {
                return 'expense-low';
            } else if (value &lt; 75) {
                return 'expense-medium';
            } else {
                return 'expense-high';
            }
        }
    },
    //the rest of the config
});
</pre>
<h2>Reconfiguring at runtime</h2>
<p>A lot of the power of PivotGrid is that it can be used by users of your application to summarize datasets any way they want. This is made possible by PivotGrid&#8217;s ability to reconfigure itself at runtime. We present one final example of a <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/reconfigurable.html">PivotGrid that can be reconfigured at runtime</a>. Here&#8217;s how we perform the reconfiguration:</p>
<pre class="brush: jscript;">
//the left axis can also be changed
pivot.topAxis.setDimensions([
    {dataIndex: 'city', direction: 'DESC'},
    {dataIndex: 'year', direction: 'ASC'}
]);

pivot.setMeasure('value');
pivot.setAggregator('avg');

pivot.view.refresh(true);
</pre>
<p>It&#8217;s easy to change the axes, dimension, aggregator and measure at any time and then refresh the data. The calculations are all performed client side so there is no need for another round-trip to the server when reconfiguring. The example linked above gives an example interface for updating a PivotGrid, though anything that can make the API calls above could be used.</p>
<p>I hope you enjoy the new components in this Ext JS 3.3 beta and look forward to comments and suggestions. Although we&#8217;re only at beta stage I think the additions are already quite robust so feel free to stress-test them.</p>
]]></description>
			<content:encoded><![CDATA[<p>One of the new components we just unveiled for the <a href="http://www.sencha.com/blog/2010/07/28/announcing-ext-js-3-3-beta-pivotgrids-calendars-and-more/">Ext JS 3.3 beta</a> is PivotGrid. PivotGrid is a powerful new component that reduces and aggregates large datasets into a more understandable form.</p>
<p>A classic example of PivotGrid&#8217;s usefulness is in analyzing sales data. Companies often keep a database containing all the sales they have made and want to glean some insight into how well they are performing. PivotGrid gives the ability to rapidly summarize this large and unwieldy dataset &#8211; for example showing sales count broken down by city and salesperson.</p>
<h2>A simple example</h2>
<p>We created <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/simple.html">an example of this scenario</a> in the 3.3 beta release. Here we have a fictional dataset containing 300 rows of sales data (<a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/simple.json">see the raw data</a>). We asked PivotGrid to break the data down by Salesperson and Product, showing us how they performed over time. Each cell contains the sum of sales made by the given salesperson/product combination in the given city and year.</p>
<p>Let&#8217;s see how we create this PivotGrid:</p>
<pre class="brush: jscript;">
var SaleRecord = Ext.data.Record.create([
    {name: 'person',   type: 'string'},
    {name: 'product',  type: 'string'},
    {name: 'city',     type: 'string'},
    {name: 'state',    type: 'string'},
    {name: 'month',    type: 'int'},
    {name: 'quarter',  type: 'int'},
    {name: 'year',     type: 'int'},
    {name: 'quantity', type: 'int'},
    {name: 'value',    type: 'int'}
]);

var myStore = new Ext.data.Store({
    url: 'salesdata.json',
    autoLoad: true,
    reader: new Ext.data.JsonReader({
        root: 'rows',
        idProperty: 'id'
    }, SaleRecord)
});

var pivotGrid = new Ext.grid.PivotGrid({
    title     : 'Sales Performance',
    store     : myStore,
    aggregator: 'sum',
    measure   : 'value',

    leftAxis: [
        {dataIndex: 'person',  width: 80},
        {dataIndex: 'product', width: 90}
    ],

    topAxis: [
        {dataIndex: 'year'},
        {dataIndex: 'city'}
    ]
});
</pre>
<p>The first half of this ought to be very familiar &#8211; we just set up a normal Record and Store. This is all we need to load our <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/simple.json">sample data</a> so that it&#8217;s ready for pivoting. This is all exactly the same code as for our other Store-bound components like Grid and DataView so it&#8217;s easy to take an existing Grid and turn it into a PivotGrid.</p>
<p>The second half of the code creates the PivotGrid itself. There are 5 main components to a PivotGrid &#8211; the store, the measure, the aggregator, the left axis and the top axis. Taking these in turn:</p>
<ul>
<li><b>Store</b> &#8211; the Store we created above</li>
<li><b>Measure</b> &#8211; the field in the data that we want to aggregate (in this case the sale value)</li>
<li><b>Aggregator</b> &#8211; the function we use to combine data into the cells. <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/docs/?class=Ext.grid.PivotGrid">See the docs</a> for full details</li>
<li><b>Left Axis</b> &#8211; the fields to break data down by on the left axis</li>
<li><b>Top Axis</b> &#8211; the fields to break data down by on the top axis</li>
</ul>
<p>The measure and the items in the axes must all be fields from the Store. The aggregator function can usually be passed in as a string &#8211; there are 5 aggregator functions built in: sum, count, min, max and avg.</p>
<h2>Renderers</h2>
<p>This is all we need to create a simple PivotGrid; now it&#8217;s time to look at a few more advanced options. Let&#8217;s start with renderers. Once the data for each cell has been calculated, the value is passed to an optional renderer function, which takes each value in turn and returns another value. <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/people.html">One of the PivotGrid examples</a> shows average heights in feet and inches but the calculated data is in decimal. Here&#8217;s the renderer we use in that example:</p>
<pre class="brush: jscript;">
new Ext.grid.PivotGrid({
    store     : myStore,
    aggregator: 'avg',
    measure   : 'height',

    //turns a decimal number of feet into feet and inches
    renderer  : function(value) {
        var feet   = Math.floor(value),
            inches = Math.round((value - feet) * 12);

        return String.format(&quot;{0}' {1}\&quot;&quot;, feet, inches);
    },
    //the rest of the config
});
</pre>
<h2>Customising cell appearance</h2>
<p>Another one of the <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/countries.html">PivotGrid examples uses a custom cell style</a>. As with the renderer, each cell has the opportunity to alter itself with a custom function &#8211; here&#8217;s the one we use in the <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/countries.html">countries example</a>:</p>
<pre class="brush: jscript;">
new Ext.grid.PivotGrid({
    store     : myStore,
    aggregator: 'avg',
    measure   : 'height',

    viewConfig: {
        getCellCls: function(value) {
            if (value &lt; 20) {
                return 'expense-low';
            } else if (value &lt; 75) {
                return 'expense-medium';
            } else {
                return 'expense-high';
            }
        }
    },
    //the rest of the config
});
</pre>
<h2>Reconfiguring at runtime</h2>
<p>A lot of the power of PivotGrid is that it can be used by users of your application to summarize datasets any way they want. This is made possible by PivotGrid&#8217;s ability to reconfigure itself at runtime. We present one final example of a <a href="http://www.sencha.com/deploy/ext-3.3-beta1-6976/examples/pivotgrid/reconfigurable.html">PivotGrid that can be reconfigured at runtime</a>. Here&#8217;s how we perform the reconfiguration:</p>
<pre class="brush: jscript;">
//the left axis can also be changed
pivot.topAxis.setDimensions([
    {dataIndex: 'city', direction: 'DESC'},
    {dataIndex: 'year', direction: 'ASC'}
]);

pivot.setMeasure('value');
pivot.setAggregator('avg');

pivot.view.refresh(true);
</pre>
<p>It&#8217;s easy to change the axes, dimension, aggregator and measure at any time and then refresh the data. The calculations are all performed client side so there is no need for another round-trip to the server when reconfiguring. The example linked above gives an example interface for updating a PivotGrid, though anything that can make the API calls above could be used.</p>
<p>I hope you enjoy the new components in this Ext JS 3.3 beta and look forward to comments and suggestions. Although we&#8217;re only at beta stage I think the additions are already quite robust so feel free to stress-test them.</p>
]]></content:encoded>
			<wfw:commentRss>http://edspencer.net/2010/07/using-the-ext-js-pivotgrid.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

