<?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>existdissolve.com &#187; Sencha Touch</title>
	<atom:link href="http://existdissolve.com/category/javascript/sencha-touch-javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://existdissolve.com</link>
	<description>the singularity of being and nothingness</description>
	<lastBuildDate>Wed, 16 May 2012 12:54:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Quick Thoughts on Sencha Architect 2</title>
		<link>http://existdissolve.com/2012/04/quick-thoughts-on-sencha-architect-2/</link>
		<comments>http://existdissolve.com/2012/04/quick-thoughts-on-sencha-architect-2/#comments</comments>
		<pubDate>Sat, 21 Apr 2012 03:11:42 +0000</pubDate>
		<dc:creator>existdissolve</dc:creator>
				<category><![CDATA[ExtJS]]></category>
		<category><![CDATA[Sencha Touch]]></category>
		<category><![CDATA[Architect 2]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://existdissolve.com/?p=2395</guid>
		<description><![CDATA[A few days ago, Sencha rolled out Sencha Architect 2, the major overhaul and rebranding of what was formerly Sencha Designer. You can check out the release blog post to get the low-down on all the new features. When I saw the news about the release, I have to say I was a bit hesitant&#8230;]]></description>
			<content:encoded><![CDATA[<p>A few days ago, Sencha rolled out <a href="http://www.sencha.com/products/architect/">Sencha Architect 2</a>, the major overhaul and rebranding of what was formerly Sencha Designer. You can check out the <a href="http://www.sencha.com/blog/sencha-architect-html5-app-builder-for-touch-and-ext-js/">release blog post</a> to get the low-down on all the new features.</p>
<p>When I saw the news about the release, I have to say I was a bit hesitant to look much further. I&#8217;ve tried Sencha Designer several times in the past, and I&#8217;ve been somewhat disappointed with it. Sure, it was great for laying out apps, but when you actually needed to *code*, it was lackluster at best. But even worse, I found it to be very buggy; it would crash at random times, and overall I found the process of trying to mockup an app to be more frustrating than anything else.</p>
<p>So initially, I wasn&#8217;t planning on even trying out the newest iteration. But then I noticed that one of the biggest additions to the product is  support for creating a full ExtJS or Touch app&#8211;not just the UI. I felt I had to take a closer look, and I&#8217;m glad I did.</p>
<h2>UI</h2>
<p>Out of the box, Architect 2 is <em><strong>worlds better</strong></em> than its previous iterations. The interface is slick and responsive, and the way the UI is organized makes the process of laying out and configuring components feel much more intuitive. One especially nice feature is that in the &#8220;Property&#8221; panel, you can toggle between commonly used configurations and the comprehensive list. Additionally, the configuration options are nicely grouped by inheritance, so you know precisely where your configs are being applied.</p>
<h2>Application Flow</h2>
<p>The coolest part of Architect 2 (to me) is that you can now *really* build applications with it. If you drink the MVC architecture Kool-Aid (and you should!), Architect 2 makes it very simple to build full-on applications.</p>
<p>For example, you can very simply choose to add controllers to your app. Within the controllers, you can customize handlers and custom methods to take care of the all of the business logic of your application.</p>
<h2>Best Practices</h2>
<p>But perhaps the best part of Architect 2 is that in the course of adding components, wiring up event handlers, and just fleshing out your app, you can instantly switch to &#8220;Code&#8221; view to see how the entire app is getting constructed behind the scenes. This gives a much welcome insight into &#8220;best practices&#8221; for developing ExtJS and Touch apps within the MVC architecture&#8211;a much desired feature that many devs have been begging for for quite a while.</p>
<p>I was happy to see that my methodology that was about 95% on point; however, the differences that I&#8217;ve noticed while reviewing the code have filled in some gaps in my understanding, which will simply make building ExtJS and Touch apps that much more fun <img src='http://existdissolve.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>So&#8230;Will I Buy It?</h2>
<p>At $399, the price tag for Sencha Architect 2 initially feels a little steep. Personally, I would not have paid that much for previous versions, purely based on my lackluster experiences during the trials. However, given how much more solid Architect 2 feels, and based on the fact that it is now geared toward full soup-to-nuts app development, I&#8217;ll have to seriously consider it.</p>
]]></content:encoded>
			<wfw:commentRss>http://existdissolve.com/2012/04/quick-thoughts-on-sencha-architect-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sencha Touch Theming: Custom UIs</title>
		<link>http://existdissolve.com/2011/09/sencha-touch-theming-custom-uis/</link>
		<comments>http://existdissolve.com/2011/09/sencha-touch-theming-custom-uis/#comments</comments>
		<pubDate>Fri, 23 Sep 2011 22:24:27 +0000</pubDate>
		<dc:creator>existdissolve</dc:creator>
				<category><![CDATA[Sencha Touch]]></category>
		<category><![CDATA[theming]]></category>

		<guid isPermaLink="false">http://existdissolve.com/?p=2236</guid>
		<description><![CDATA[During the course of developing your Sencha Touch app, you will inevitably get around to theming&#8230;after all, while the default styles are nice, they don&#8217;t exactly scream individuality. Fortunately, Sencha Touch makes theming ridiculously easy, and there are a lot of resources available to help with getting started with that. But let&#8217;s talk about a&#8230;]]></description>
			<content:encoded><![CDATA[<p>During the course of developing your Sencha Touch app, you will inevitably get around to theming&#8230;after all, while the default styles are nice, they don&#8217;t exactly scream individuality. Fortunately, Sencha Touch makes theming ridiculously easy, and there are a lot of resources available to help with getting started with that.</p>
<p>But let&#8217;s talk about a specific example. Let&#8217;s imagine that you want to simply change the background color on your app&#8217;s toolbars. The first thing you&#8217;ll probably do is pop open Firebug or Developer Tools to inspect the CSS that&#8217;s being applied to your toolbar. Unless you&#8217;ve already customized it, you&#8217;ll probably seem something like this:</p>
<p><a href="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.46.49-PM.png"><img class="size-full wp-image-2241 alignnone" style="display: block;" title="Screen Shot 2011-09-26 at 9.46.49 PM" src="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.46.49-PM.png" alt="" width="581" height="161" /></a></p>
<p>I&#8217;ve highlighted &#8220;x-toolbar-dark&#8221;, because by default, the &#8220;UI&#8221; configuration option for Ext.Toolbar is set to &#8220;dark,&#8221; which applies the &#8220;x-toolbar-dark&#8221; class to your toolbar (it will apply &#8220;x-toolbar-light&#8221; if you specify &#8220;light&#8221; for ui&#8230;more on this later).</p>
<p>Here&#8217;s what the toolbar actually looks like:</p>
<p><a href="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.46.27-PM.png"><img class="size-full wp-image-2242 alignnone" style="display: block;" title="Screen Shot 2011-09-26 at 9.46.27 PM" src="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.46.27-PM.png" alt="" width="322" height="51" /></a></p>
<p>If you inspect the properties of this CSS class, you should see something like this:</p>
<ul>
<li title="background-color:#456f8d;">background-color: #456F8D;</li>
<li title="background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #9cbacf), color-stop(2%, #5182a5), color-stop(100%, #395c75));">background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #9cbacf), color-stop(2%, #5182a5), color-stop(100%, #395c75));</li>
<li title="background-image:-webkit-linear-gradient(#9cbacf,#5182a5 2%,#395c75);">background-image: -webkit-linear-gradient(#9cbacf,#5182a5 2%,#395c75);</li>
<li title="background-image:linear-gradient(#9cbacf,#5182a5 2%,#395c75);">background-image: linear-gradient(#9cbacf,#5182a5 2%,#395c75);</li>
<li title="border-color:#000">border-color: black;</li>
</ul>
<p>Nothing too crazy here&#8230;just some background-image gradients to give the toolbar a nice textured feel. Now at this point, you might be tempted to do something crazy, something like creating a new class in an <strong><em>extra</em></strong> custom stylesheet to override these style rules. Or, you might add a custom class via the Ext.Toolbar&#8217;s &#8220;cls&#8221; config, and add the styles for this custom class in your custom stylesheet.</p>
<p>While both of these options will certainly work, they miss out on the power of theming within Sencha Touch. So let&#8217;s look at a better way to approach this.</p>
<h2>Toolbar UI</h2>
<p>If you look at the <a href="http://dev.sencha.com/deploy/touch/docs/?class=Ext.Toolbar">documentation for Ext.Toolbar </a>(as well as several of the other common components), you&#8217;ll notice that it has a config option for &#8220;ui&#8221;. By default, you can specify either &#8220;dark&#8221; or &#8220;light,&#8221; which is what applies either the &#8220;x-toolbar-dark&#8221; or &#8220;x-toolbar-light&#8221; classes to our toolbar. So knowing this, the ideal approach to customizing our toolbar&#8217;s style is not by creating custom, external style rules to override or circumvent default Sencha Touch styling, but rather to create our own &#8220;ui&#8221; that we can use in the configuration of our Ext.Toolbar itself.</p>
<p>Fortunately, this is ridiculously easy&#8230;but first, some context <img src='http://existdissolve.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Default Toolbar UIs</h2>
<p>As mentioned, the Toolbar has two default UIs: dark and light. By specifying either of these in the configuration of your Ext.Toolbar, you can easily switch between the two to get the feel that you would like (this is especially helpful if you have stacked toolbars).  Let&#8217;s take a look at how these UIs are created.</p>
<p>First, we&#8217;ll need to find the .scss (Sassy CSS) file that generates the toolbar CSS classes. You can find that here:</p>
<p><strong>sencha-touch-1.1.0/resources/themes/stylesheets/sencha-touch/default/widgets/_toolbar.scss</strong></p>
<p>A ways down the page, you&#8217;ll see something like the following:</p>
<pre>@include sencha-toolbar-ui('dark', darken($base-color, 10%));
@include sencha-toolbar-ui('light', $base-color);</pre>
<p>Here, our two default UIs are created. This is done by using the <strong>sencha-toolbar-ui</strong> <a href="http://sass-lang.com/#mixins">&#8220;mixin,&#8221;</a> which is really just a mechanism to allow you reuse chunks of code to construct CSS classes. The great part about mixins, though, is that you can utilize arguments, so it makes creating custom iterations of the same family of classes super easy.</p>
<p>Now let&#8217;s take a look at the mixin itself:</p>
<pre>@mixin sencha-toolbar-ui($ui-label, $color, $gradient: $toolbar-gradient) {
   $toolbar-border-color: darken($color, 50%);
   $toolbar-button-color: darken($color, 10%);
   .x-toolbar-#{$ui-label} {
      @include background-gradient($color, $gradient);
      border-color: $toolbar-border-color;
      .x-toolbar-title {
         @include color-by-background($color);
         @include bevel-by-background($color);
      }
      .x-button, .x-field-select .x-input-text, .x-field-select:before {
         @include toolbar-button($toolbar-button-color, $gradient);
      }
   }
}</pre>
<p>As you can see, the mixing takes up to 3 arguments:</p>
<ul>
<li>The name of the UI</li>
<li>The base color for the UI</li>
<li>The type of gradient to use for the UI (defaults to the variable $toolbar-gradient)</li>
</ul>
<p>Then, based on the arguments passed, this mixin will create a CSS class in the form of &#8220;x-toolbar-[UI Name]&#8220;, and will additionally create classes that riff on the color and gradient that are specified for the overall UI. This will give the toolbar a unified &#8220;feel&#8221; if it contains buttons.</p>
<h2>Creating our Own Toolbar UI</h2>
<p>While this UI/SASS/mixin stuff can be a little overwhelming at first, hopefully you see now how it starts to come together. Since we know that the &#8220;dark&#8221; and &#8220;light&#8221; UIs for the toolbar are crafted simply by using the sencha-toolbar-ui mixin, it&#8217;s pretty clear how we need to proceed to create our own UI. So let&#8217;s do that now.</p>
<p>In <strong>sencha-touch-1.1.0/resources/sass/</strong>, I&#8217;ve created a custom .scss file (I&#8217;ve called it &#8220;custom&#8221;&#8230;pretty original, I know). In this .scss file, I&#8217;m going to create a custom toolbar UI. Since &#8220;blue&#8221; is way to predictable for a developer, I want to try something sheik, but safe. How about a nice &#8220;charcoal&#8221; UI?</p>
<p>Here&#8217;s how we do it:</p>
<div>
<pre>$base-color: #588aad; // go big blue!
$include_default_icons: false;
@import 'sencha-touch/default/all';
@include sencha-panel;
@include sencha-buttons;
@include sencha-sheet;
@include sencha-picker;
@include sencha-tabs;
@include sencha-toolbar;
@include sencha-toolbar-forms;
@include sencha-indexbar;
@include sencha-list;
@include sencha-layout;
@include sencha-form;
@include sencha-msgbox;
@include sencha-loading-spinner;

@include pictos-iconmask("bookmarks");
@include pictos-iconmask("compose");
@include pictos-iconmask("trash");
@include pictos-iconmask("search");
@include pictos-iconmask("my-logo");
@include pictos-iconmask("bookmark2");

<strong>@include sencha-toolbar-ui('charcoal', #333333,'glossy');</strong></pre>
</div>
<p>Ok, 98% of the code above has nothing to do with our custom UI. I just wanted to include it, in case you&#8217;ve never seen an .scss file. The most important line for our UI is the last one.</p>
<p>What? One line? Is that really all there is to creating a custom toolbar UI? The simple answer is <strong>YES</strong>.</p>
<p>Easy, right? And this is precisely why I advocate for creating the custom UI, over and against modification of a custom stylesheet. With the custom UI, we don&#8217;t need to do anything else besides this one line of code here. Any maintenance moving forward (like tweaking for a more nuanced &#8220;charcoal&#8221; color) will only require a quick modification here. No extra style sheet to worry about, which is always a good thing.</p>
<h2>Using the Custom UI</h2>
<p>Alright, so we&#8217;ve created our custom UI. How do we use it?</p>
<p>Well, first, we&#8217;re going to need to recompile our app&#8217;s stylesheet.</p>
<p>In Terminal, navigate to <strong>sencha-touch-1.1.0/resources/sass</strong> (where we created our custom .scss file), and then type &#8220;<strong>compass compile</strong>&#8220;. If everything goes through ok, you should now see a &#8220;custom.css&#8221; (or whatever you named it) in the <strong>sencha-touch-1.1.0/resources/css</strong> folder.</p>
<blockquote><p>If you have <strong><em>no idea</em></strong> what&#8217;s going on here, take a look at this article on <a title="Sencha Touch Theming: Getting Started" href="http://existdissolve.com/2011/03/sencha-touch-theming-getting-started/">getting setup for theming in Sencha Touch</a>.</p></blockquote>
<p>Take this path to your custom CSS file and add it to your main application file so that it&#8217;s using it as the main CSS.</p>
<p>Good? Ok, now we can apply our custom UI to a toolbar!</p>
<pre>var myToolbar = new Ext.Toolbar({
   dock: "top",
   title: "Fancy Charcoal Toolbar in the House!",
  <strong> ui: "charcoal"</strong>
});</pre>
<p>That&#8217;s it! Save your work, refresh your browser, and you should now see your app with a sheik, sophisticated charcoal toolbar <img src='http://existdissolve.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The final result?</p>
<p><a href="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.50.32-PM.png"><img title="Screen Shot 2011-09-26 at 9.50.32 PM" src="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.50.32-PM.png" alt="" width="323" height="49" /></a></p>
<p>And the underlying HTML:</p>
<p><a href="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.50.12-PM.png"><img title="Screen Shot 2011-09-26 at 9.50.12 PM" src="http://existdissolve.com/wp-content/uploads/2011/09/Screen-Shot-2011-09-26-at-9.50.12-PM.png" alt="" width="587" height="158" /></a></p>
<p>(Notice it&#8217;s exactly the same as before, but now with the new UI class of &#8220;charcoal&#8221;)</p>
<h2>Wrapping Up</h2>
<p>I can&#8217;t understate the point enough that what&#8217;s been outlined above has only scratched the surface of what&#8217;s possible. But hopefully it demonstrates some of the really cool things that can be accomplished with very little effort, and in such a way that is a natural extension of Sencha Touch&#8217;s powerful theming capabilities.</p>
]]></content:encoded>
			<wfw:commentRss>http://existdissolve.com/2011/09/sencha-touch-theming-custom-uis/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sencha Touch EditableList</title>
		<link>http://existdissolve.com/2011/09/sencha-touch-editablelist/</link>
		<comments>http://existdissolve.com/2011/09/sencha-touch-editablelist/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 02:54:16 +0000</pubDate>
		<dc:creator>existdissolve</dc:creator>
				<category><![CDATA[Sencha Touch]]></category>

		<guid isPermaLink="false">http://existdissolve.com/?p=2229</guid>
		<description><![CDATA[Yeah, I know, I&#8217;m not the first person to the &#8220;create an EditableList for Sencha Touch&#8221; party. In fact, if you Google &#8220;sencha touch editable list,&#8221; you&#8217;ll find a lot of really nice code that will let you pretty easily integrate basic delete/sort functionality into your Sencha Touch app. However, none of the offerings I&#8230;]]></description>
			<content:encoded><![CDATA[<p>Yeah, I know, I&#8217;m not the first person to the &#8220;create an EditableList for Sencha Touch&#8221; party. In fact, if you Google &#8220;sencha touch editable list,&#8221; you&#8217;ll find a lot of really nice code that will let you pretty easily integrate basic delete/sort functionality into your Sencha Touch app.</p>
<p>However, none of the offerings I ran across really fit the bill of what I was wanting, in terms of interface. Plus, it&#8217;s so much MORE FUN to build your own, right? Right!</p>
<h2>What I Wanted</h2>
<p>My wish list for my EditableList was pretty straightforward: I wanted it to behave *more or less* like my iPhone&#8217;s Mail app list editing. This includes:</p>
<ul>
<li>One click to do a batch deletion/archiving of list items (btw, I absolutely HATE the same interface in the default iPhone text message app&#8230;)</li>
<li>The ability to swipe-delete individual messages</li>
<li>Some animations to make it somewhat mimic the iPhone Mail app&#8217;s animations (think &#8220;sliding&#8221; the deletion selectors in and out)</li>
</ul>
<p>In addition to this, I wanted more or less everything&#8211;functionality, layout, interface&#8211;to be baked into my one custom extension. One of the things I didn&#8217;t like about some of the other solutions I found is that they required a certain structure external to the list (e.g., docked toolbars in certain places, etc.) that had to be in place before even using the list.</p>
<p>While mine makes its own assumptions, it takes care of a lot of the list-manipulation interfacy-stuff on its own. This might create some conflicts in certain scenarios, but oh well <img src='http://existdissolve.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Some Highlights</h2>
<p>There&#8217;s a fair amount of code, so I&#8217;m not going to walk through it line by line. It&#8217;s fairly well-commented, so feel free to walk through it on your own <strong><a href="https://github.com/existdissolve/Ext.ux.EditableList">over at the GitHub</a></strong>. I did, however, want to call attention to some bits I thought were pretty cool.</p>
<p>This project was the first where I&#8217;ve ever really used the relayEvents() method. Here&#8217;s what the docs have to say about it:</p>
<blockquote>
<div>Relays selected events from the specified Observable as if the events were fired by <tt><strong>this</strong></tt>.</div>
</blockquote>
<p>So what does this mean? Well, suppose we&#8217;re adding events to our main Ext.ux.EditableList. In my example, I added &#8220;beginEdit&#8221; and &#8220;endEdit&#8221; events. I use these throughout to do certain things based on the &#8220;state&#8221; of editing that is currently in effect. However, my EditableList also has child objects, like buttons, toolbars, etc., which will more than likely need to know about the same &#8220;state&#8221; in order to do what they need to do (go hide themselves, change their text, whatever). So given this reality, wouldn&#8217;t it be nice if they could all participate in the same events? That is, instead of running every change to button X through the &#8220;endEdit&#8221; listener of the main EditableList, how great would it be if I could also have a listener on the button itself for the same &#8220;endEdit&#8221; event?</p>
<p>This is the magic of relayEvents(). By invoking relayEvents on my EditableList&#8217;s child components, they can all be &#8220;aware&#8221; of the same events that are happening within the lifecycle of the EditableList, and react accordingly to the events as they occur. Not only does this feel more intuitive, but it allows for much more segregation of logic within the code.</p>
<h2>An Example</h2>
<p>Within the EditableList, there is a Toolbar that gets added to the EditableList&#8217;s parent panel to house a delete button (sort of like the delete button at the bottom of the iPhone mail app when you click the &#8220;Edit&#8221; button).  Obviously, we only really want this Toolbar to display when we&#8217;re in &#8220;edit&#8221; mode, and would prefer that it go away when edit mode stops. Using relayEvents(), we can set up listeners on the Toolbar itself for the events that are raised by the EdtiableList.</p>
<p>Here&#8217;s a stripped-down example of what this looks like:</p>
<pre>Ext.ux.EditableList = Ext.extend(Ext.List, {
   ...some config stuff...,
   initComponent: function() {
      this.listeners = {
         "beginEdit": function(list,mode) {
            ...logic here...
         },
         "endEdit": function(list,mode) {
            ....logic here...
         }
      };
      Ext.ux.EditableList.superclass.initComponent.call(this);
      // add new events
      this.addEvents("beginEdit","endEdit");
   },
   addDeleteBar: function() {
      var bbar = new Ext.Toolbar({
         ...some config...,
         listeners: {
            "endEdit": function(list,mode) {
               this.hide(this.showAnimation);
            }
         }
      });
      bbar.relayEvents(this,["endEdit"]);
      ...finish adding toolbar...
   },
   someOtherFunction: function() {
      this.fireEvent("endEdit",this,"multi");
   }
})</pre>
<p>Above, we can see that two new events&#8211;&#8221;beginEdit&#8221; and &#8220;endEdit&#8221;&#8211;have been added to the EditableList, and we have listeners applied to the EditableList to execute certain functionality when those events fire. However, because we&#8217;ve used relayEvents() on our Toolbar, we can also listen for the same events in our Toolbar, even though these events haven&#8217;t been explicitly added to the Toolbar.</p>
<h2>Wrapping Up</h2>
<p>If you can&#8217;t tell, I think relayEvents() is really nifty. Yes, NIFTY. I really like the ability to manage the functionality of related, but disparate components off of the same events. As I mentioned before, not only does this help to maintain consistency with how each component within EditableList understands the &#8220;state&#8221;, but it also helps keep the code clean, since we&#8217;re dealing with component-specific logic within the listeners of the components themselves, rather than in one catch-all listener at the highest level.</p>
]]></content:encoded>
			<wfw:commentRss>http://existdissolve.com/2011/09/sencha-touch-editablelist/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sencha Touch: JumpToNode and the NestedList</title>
		<link>http://existdissolve.com/2011/09/sencha-touch-jumptonode-and-the-nestedlist/</link>
		<comments>http://existdissolve.com/2011/09/sencha-touch-jumptonode-and-the-nestedlist/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 12:00:28 +0000</pubDate>
		<dc:creator>existdissolve</dc:creator>
				<category><![CDATA[Sencha Touch]]></category>
		<category><![CDATA[NestedList]]></category>

		<guid isPermaLink="false">http://existdissolve.com/?p=2210</guid>
		<description><![CDATA[Sencha Touch&#8217;s NestedList is an excellent component for creating the compact &#8220;drill-down&#8221; effect that we&#8217;re all used to on our mobile devices. It&#8217;s super-flexible, too. Whether you have a canned set of items, or need to retrieve each &#8220;level&#8221; via AJAX, it&#8217;ll handle it. I&#8217;ve used NestedList quite a bit, and have been generally happy&#8230;]]></description>
			<content:encoded><![CDATA[<p>Sencha Touch&#8217;s <a href="http://dev.sencha.com/deploy/touch/examples/nestedlist/">NestedList is an excellent component for creating the compact &#8220;drill-down&#8221; effect </a>that we&#8217;re all used to on our mobile devices. It&#8217;s super-flexible, too. Whether you have a canned set of items, or need to retrieve each &#8220;level&#8221; via AJAX, it&#8217;ll handle it.</p>
<p>I&#8217;ve used NestedList quite a bit, and have been generally happy with it. One of the issues I&#8217;ve come across, though, is that it does not (as far as I&#8217;m aware, at least) support jumping around to arbitrary nodes with the NestedList.</p>
<p>Huh? So here&#8217;s an example <img src='http://existdissolve.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Let&#8217;s say you have a bunch of products that exist within categories of variable depth. Once you reach the &#8220;product&#8221; level of your NestedList, you can out-of-the-box call getDetailCard(), build out your detail view, and be done with it. NestedList will take care of the navigation bits, and your site&#8217;s visitor will get a nice &#8220;back&#8221; button to return to the category list they used to get to the detail product.</p>
<p>Fine and dandy. BUT&#8230;what if you have links on your detail &#8220;card&#8221; to related products? Maybe these products exist in the same category, at the same &#8220;depth&#8221; in the nested list. But maybe instead they are in an entirely different category, one that&#8217;s two levels higher, or three levels deeper. What should you do?</p>
<p>Well, you could pop up a window (or something) that contains the details for that &#8220;related&#8221; product. And maybe within that popup you could drive any *additional* links to continue with the pop-up mode indefinitely. I suppose that works, but it feels a bit clunky. And you&#8217;ve also lost context. While the context of the original detail card is preserved, any subsequent navigation is essentially orphaned.</p>
<p>So let&#8217;s say that instead of trying to wrangle the pop-up window solution, you&#8217;d rather just keep with the NestedList model, and &#8220;jump&#8221; to the appropriate place in the tree. Unfortunately, from what I can tell, there is no way out of the box to do this with NestedList.  Fortunately, there is a workaround&#8230;</p>
<blockquote><p><strong>BIG DISCLAIMER!</strong> What follows assumes that your NestedList implementation is using a static set of data (e.g., all the data is set when the NestedList is created, and not determined via AJAX as each &#8220;level&#8221; is loaded).</p></blockquote>
<p><span class="Apple-style-span" style="font-size: 26px; line-height: 28px;">Some Context</span></p>
<p>If you want to <a href="#jump2node">jump to the solution</a>, feel free. However, I want to take some time to outline my understanding of the NestedList, just so the solution makes sense if you&#8217;re trying to follow along. Cool? Okay.</p>
<p>First, there&#8217;s something you need to know about the NestedLIst. It&#8217;s built to be as &#8220;light&#8221; as possible at any given time. What do I mean by that? Well, if you take a look at the underlying HTML that&#8217;s generated for each &#8220;level&#8221; of the tree, you&#8217;ll notice that the only &#8220;levels&#8221; that exist at any one time are the ones that are absolutely necessary to manage the current level that you&#8217;re &#8220;on&#8221;.</p>
<p>So instead of rendering the whole gosh-darn thing right up front (which could be MASSIVE if the NestedList is large and complex), only the bits that are needed are rendered at any one time; the parts that are not are simply removed, and re-rendered later on if requested. In other words, as you move from list to list, drilling your way down the hierarchy, lists are being constantly added and removed, depending on the needs of your view at any given point in time.</p>
<p>While this definitely makes a lot sense from a performance standpoint (after all, you don&#8217;t necessarily want or need the entire form of the NestedList&#8217;s content rendered all the time), it does create a problem for our dream of arbitrarily jumping to node X in the NestedList. After all, if only the necessary lists are available at any given time, we can&#8217;t just jump willy-nilly, hoping that our destination exists within the currently rendered lists. If it does, fine and great (ok, not really, but&#8230;), but otherwise, we&#8217;ll generate errors, break navigation, or both.</p>
<h2>What To Do, What To Do</h2>
<p>So the situation is hopeless, right? Since ALL of the lists aren&#8217;t rendered at one time, we can&#8217;t possibly implement a solution for jumping to random nodes in the tree, right?</p>
<p>Wrong. While it&#8217;s true that the dynamic nature of the NestedList is something we have to work around (or with, as the case may be), it&#8217;s not impossible or even hard. This is because I left out an important point. Even though the entire NestedList is not <em><strong>rendered</strong></em> at any one time, this doesn&#8217;t mean that we don&#8217;t know what our NestedList&#8217;s <em><strong>data</strong></em> looks like, or where we might find node X within the hierarchy. To the contrary, in our NestedList&#8217;s fancy <a href="http://dev.sencha.com/deploy/touch/docs/?class=Ext.data.TreeStore">TreeStore</a>, we&#8217;ve got all the data we need to be able to figure out where the node we want actually lives. And armed with this knowledge, and an basic understanding of how the lists are being dynamically added and removed from the NestedList, we can begin clawing our way toward our dream of arbitrary NestedList navigation!</p>
<h2>Now We Begin</h2>
<p>So let&#8217;s get started. First, since we have no OOTB way of accomplishing this goal with the NestedList&#8217;s existing methods, we&#8217;ll need to add our own. And since we want this to be something of a drag-and-drop solution, let&#8217;s go ahead and make a custom extension of the NestedList class.</p>
<pre>Ext.ns('Ext.ux');
Ext.ux.NestedList = Ext.extend(Ext.NestedList, {
    jumpToNode: function(nodeInfo, doSelect, hideActive) {
    ...
    }
});</pre>
<p>We&#8217;ll come back to this in more detail, but that&#8217;s the skeleton of our custom class. Obviously, we could do a lot more, but for this post, we&#8217;ll just be adding a single new method, <strong>jumpToNode()</strong>.</p>
<p>WIth our new class created, let&#8217;s use it in our app:</p>
<pre>App.views.MyNestedList = Ext.extend(Ext.ux.NestedList, {
   fullscreen: true,
   iconCls: "home",
   store: "Navigation",
   displayField: "text",
   title: "Custom NestedList",
   initComponent: function() {
      App.views.MyNestedList.superclass.initComponent.call(this);
   },
   getDetailCard: function(record,parentrecord) {
      var data = record.attributes.record.data;
      var title = data.title;
      var target= data.target;
      var type  = data.type;
      Ext.ControllerManager.get("Navigation").getContent(target,title,type);
   }
});</pre>
<p>Nothing important here&#8230;just a vanilla NestedList, but using our fancy new custom class. As with all NestedLists, once we get to a &#8220;leaf&#8221; node in our data, the getDetailCard() method will fire, and we can set up how we handle the generation of that &#8220;card&#8221;. In my app, I send off an AJAX request to get the content from the server, handle the response, and dynamically add a card using the retrieved data&#8230;no biggie.</p>
<h2>Where it Gets Interesting</h2>
<p>To this point, we&#8217;ve not doing anything outside of the normal NestedList model. In fact, if we stopped here, we would have wasted time creating the custom class. But that would make this post pointless, so we won&#8217;t do that!</p>
<p>So let&#8217;s imagine that in the content we receive back from the server, we have HTML that contains links to other content in our application. Or to think of it in terms of the NestedList, our generated DetailCard has links to other potential DetailCards.</p>
<p>In my app, I return these *special* links with a class attribute of &#8220;<strong>cardlink&#8221;</strong> (e.g., &lt;a href=&#8221;&#8230;&#8221; class=&#8221;cardlink&#8221;&gt;&#8230;&lt;/a.&gt;). This allows me to do something kind of cool in the generation of my DetailCard. Here&#8217;s a snippet from my &#8220;Navigation&#8221; controller:</p>
<pre>Ext.regController("Navigation",{
   getContent: function(title,target,type) {
      ... generate detail card content ...
      var view = App.views.MyNestedList;
      // add detail card to NestedList
      view.add(detailcard);
      // add listeners to *special* links
      Ext.get("content_wrapper").select("a[class=cardlink]").each(function(){
         this.on("click",function(){
            // when link is selected, invoke find() method
            me.find(target,title,type)
         });
      }),
      find: function(target) {
         var tree = App.views.MyNestedList.store.tree;
         // get the node from the tree store
         var node = tree.getNodeById(target);
         if(node) {
            App.views.MyNestedList.jumpToNode(node,true,false);
         }
      }
   )}
)}</pre>
<p>Obviously, I&#8217;m not showing everything here, but the important bits are there. First, I add my new DetailCard to my NestedList. Then, I loop over each link within my DetailCard&#8217;s content (I have a div with an ID of &#8220;content_wrapper&#8221;). If the link has the class of &#8220;cardlink,&#8221; I know it points to another DetailCard within my app, so I add a listener for the click event to fire the find() method. In the find() method of my controller, I lookup the node from the NestedList&#8217;s store, and&#8212;FINALLY&#8211;invoke the method jumpToNode() which we added to our custom NestedList class.</p>
<p><a name="jump2node"></a></p>
<h2>jumpToNode() In a Nutshell</h2>
<p>jumpToNode() takes 3 arguments. Here they are:</p>
<ul>
<li><strong>nodeInfo</strong> [required]: This is basically which node you want to jump to. You can either look it up beforehand, retrieve the node, and pass it through to this method, or you can simply pass the id of the node you want.</li>
<li><strong>doSelect</strong> [optional, default: true]: This argument tells the method whether or not you want  to apply the selectedClass to the parent items of the passed node</li>
<li><strong>hideActive</strong> [options, default: false]: This argument helps prevent a momentary flicker of the target node&#8217;s parent when switching from DetailCard to DetailCard. <em><strong>NOTE:</strong> This requires a small override tweak to Ext.layout.CardLayout&#8217;s setActiveItem() method (more below)</em></li>
</ul>
<p>Enough of those boring details, let&#8217;s get to some code! Back in our custom extension of the NestedList class, we can begin crafting our jumpToNode() method.</p>
<pre>Ext.ux.NestedList = Ext.extend(Ext.NestedList, {
   jumpToNode: function(nodeInfo, doSelect, hideActive) {
      var me = this;
      ...
      var tree = me.store.tree;
      // loop over all child lists in this NestedList and remove them
      // we want a clean slate to work with
      for(i=(me.items.length-1);i &gt;= 1;i--){
         me.remove(me.items.getAt(i));
      }
      // at the top level list, deselect any selected records
      me.items.getAt(0).deselect(me.items.getAt(0).getSelectedRecords());
      ....
   }
});</pre>
<p>The first important part of the code is this snippet. Remember how I said that NestedList dynamically adds AND removes lists from the main component? Well, if we&#8217;re going to jump to an arbitrary point in the NestedLIst, we need a clean slate. This snippet basically rolls over the current state of the NestedList, and removes all items, except for the top-level list. In a nutshell, it&#8217;s a form of a &#8220;return to home&#8221; method. If we stopped here, we&#8217;d basically be back at the root of our NestedList.</p>
<blockquote><p>BTW, this &#8220;return to home&#8221; functionality is a potentially handy method to have as its own animal. Feel free to break it out into another method in this custom class of NestedList if you want.</p></blockquote>
<p>Now that we&#8217;re back at home base, so to speak, we can start building up the new collection of lists that will form the path to our desired node.</p>
<pre>var nodes = [];
var depth = node.getDepth();
var nid = node.id;
// loop over depth, get node ids of node hierarchy
for(i=0;i&lt;depth;i++) {
   nodes.push(nid);
   nid =  tree.nodeHash[nid].parentNode.id;
}</pre>
<p>Pretty straightforward here. Since we know our destination (remember, we already passed in the node/nodeid of our desired target&#8230;), we know some really important information, namely, what level our node is at. Using the node&#8217;s getDepth() method, we can now do a quick loop to build a dirty array of our node&#8217;s parents by tapping into the handy &#8220;nodehash&#8221; we have of all our NestedList&#8217;s nodes on the main NestedList store&#8217;s tree.</p>
<blockquote><p>Curious about the nodeHash? In your debugging tools, set a breakpoint somewhere in this process and inspect the &#8220;tree&#8221;&#8211;you&#8217;ll see the nodeHash, which is basically an collection of key-value pairs for each node in the NestedList store&#8217;s tree.</p></blockquote>
<p>Ok, at this point, our &#8220;nodes&#8221; array has a listing&#8211;from child to ancestor&#8211;of all the nodes that build the path to our target. It&#8217;s now time to actually build out our new lists.</p>
<pre>// reverse the node array, and we'll build out the new lists
nodes = nodes.reverse();
var newlist,nextlist,prevlist,child,tmpnode,curridx;
// now loop over hierarchy of nodes, adding lists as we go along
for(i=0;i&lt;nodes.length;i++) {
   tmpnode = tree.getNodeById(nodes[i]);
   // if it's not a leaf, we're working with a list
   if(!tmpnode.leaf) {
      // get the sublist
      newlist = me.getSubList(tmpnode);
      // add it to the nestedlist
      nextlist = me.addNextCard(newlist.recordNode);
      me.layout.setActiveItem(nextlist,"fade",hideActive);
      // if doSelect is true, get target node and select it
      if(doSelect) {
         // get the index of the list we just added
         curridx = me.items.indexOf(nextlist);
         // get the one before it
         prevlist = me.items.getAt(curridx-1);
         // find the child node that corresponds to the item in the hierarchy
         child = prevlist.getNode(tmpnode.getRecord())
         prevlist.selModel.select(child)
      }
   }
   // is a leaf; will probably want to fire onItemTap()
   else {
      var idx = nextlist.store.find("id",tmpnode.id);
      if(doSelect) {
         // should be the last added list
         prevlist = me.items.getAt(curridx);
         child = prevlist.getNode(tmpnode.getRecord())
         prevlist.selModel.select(child)
      }
      me.onItemTap(nextlist,idx);
   }
}</pre>
<p>The first thing we need to do is to reverse our node array. It&#8217;s currently ordered from child-to-ancestor, but we need to build from the top down.</p>
<p>With that done, we begin a loop over the array of nodes., At each iteration, we retrieve the node from our NestedList&#8217;s TreeStore using getNodeById(). With this, we look up the appropriate &#8220;subList&#8221; from our NestedList, which is basically what we&#8217;ll use for creating the List &#8220;card&#8221; at each level.</p>
<p>Once we&#8217;ve added the subList card, we need to take a brief detour and set the &#8220;activeItem&#8221; for our NestedList. If we don&#8217;t do this, the automatic &#8220;navigation&#8221; that&#8217;s added to our NestedList&#8217;s toolbar will be broken&#8230;and we don&#8217;t want that.</p>
<blockquote><p>NOTE: Here&#8217;s where the &#8220;hideActive&#8221; argument comes into play. I would *strongly* suggest setting it to &#8220;true&#8221;, but hey, it&#8217;s your app <img src='http://existdissolve.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  If you want to use it, you&#8217;ll need to slightly override the Ext.layout.CardLayout class setActiveItem() method (included below)</p></blockquote>
<p>With that out of the way, we can now handle the &#8216;doSelect&#8221; argument. As mentioned above, if true, this will tell our custom NestedList to select the parent nodes of our target. If you&#8217;re confused by what this means, take a second to try out a vanilla NestedList. As you navigate down, and then use the toolbar nav to go &#8220;back,&#8221; you&#8217;ll notice that the node you previously clicked will be momentarily &#8220;selected,&#8221; before reverting to an unselected state. The doSelect() method allows the custom NestedList to mimic that behavior. If you don&#8217;t care about/want that, you can skip it.</p>
<p>All of that was for non-leaf items. Once our loop gets to a leaf, it will break into the &#8220;else&#8221;. Since we don&#8217;t need to add any more list cards (we&#8217;re at the leaf node, remember), all that&#8217;s left is to handle our doSelect() and then to fire the onItemTap() method. This automatically handles what would *normally* happen if someone was navigating a NestedList by clicking through the hierarchy. When onItemTap() is invoked, our NestedLists&#8217;s getDetailCard() method should automatically fire, and the user should have the experience of fluidly moving from one DetailCard to another, without needing to re-navigate through the entire hierarchy. And furthermore, since we&#8217;ve built out the lists in a way that the OOTB NestedList understands, the toolbar nav should just work, even though we&#8217;ve jumped arbitrarily from one NestedList node to another.</p>
<h2>jumpToNode &#8211; The Whole Enchilada</h2>
<pre>Ext.ux.NestedList = Ext.extend(Ext.NestedList, {
   jumpToNode: function(nodeInfo,doSelect,hideActive) {
      var me = this,
      hideActive = hideActive==undefined ? me.layout.hideActive : hideActive,
      doSelect = doSelect==undefined ? false : doSelect,
      tree = me.store.tree,
      nodes = [],
      node = nodeInfo;
      if(Ext.isString(nodeInfo)) {
         // do lookup of node based on id
         node = tree.getNodeById(nodeInfo);
         if(!nodeInfo) {
            return false;
         }
      }
      // first things first; remove existing lists and detail cards from cur nested list
      for(i=(me.items.length-1);i &gt;= 1;i--){
         me.remove(me.items.getAt(i));
      }
      // at the top level list (which we'll leave), deselect any selected records
      me.items.getAt(0).deselect(me.items.getAt(0).getSelectedRecords());
      // get the depth of the node
      var depth = node.getDepth();
      var nid = node.id;
      // loop over depth, get node ids of node hierarchy
      for(i=0;i&lt;depth;i++) {
         nodes.push(nid);
         nid =  tree.nodeHash[nid].parentNode.id;
      }
      // reverse the node array, and we'll build out the new lists
      nodes = nodes.reverse();
      var newlist,
          // set nextlist to our root list, in case we have leaf items at root
          nextlist = me.items.getAt(0),
          // also set prevlist to our root list, to prevent issues if leaf is at root
          prevlist = me.items.getAt(0),
          child,
          tmpnode,
          curridx = 0;
      // now loop over hierarchy of nodes, adding lists as we go along
      for(i=0;i&lt;nodes.length;i++) {
         tmpnode = tree.getNodeById(nodes[i]);
         // if it's not a leaf, we're working with a list
         if(!tmpnode.leaf) {
            // get the sublist
            newlist = me.getSubList(tmpnode);
            // add it to the nestedlist
            nextlist = me.addNextCard(newlist.recordNode);
            me.layout.setActiveItem(nextlist,"fade",true);
            if(doSelect) {
               // get the index of the list we just added
               curridx = me.items.indexOf(nextlist);
               // get the one before it
               prevlist = me.items.getAt(curridx-1);
               // find the child node that corresponds to the item in the hierarchy
               child = prevlist.getNode(tmpnode.getRecord())
               // if doSelect is true, fire select on current node
               prevlist.selModel.select(child)
            }
         }
         // is a leaf; will probably want to fire onItemTap()
         else {
            var idx = nextlist.store.find("id",tmpnode.id);
            // if we want to select the node AND prevlist is NOT undefined (e.g., a root
            if(doSelect &amp;&amp; prevlist != undefined) {
               // should be the last added list
               prevlist = me.items.getAt(curridx);
               child = prevlist.getNode(tmpnode.getRecord())
               prevlist.selModel.select(child)
            }
            me.onItemTap(nextlist,idx);
         }
      }
   }
});</pre>
<h2>setActiveItem Override</h2>
<p>If you&#8217;re using the &#8220;hideActive&#8221; argument, here&#8217;s the override to setActiveItem in the Ext.layout.CardLayout class:</p>
<pre>Ext.override(Ext.layout.CardLayout, {
   setActiveItem: function(newCard, animation<strong>,hideActive</strong>) {
   var me = this,
      owner = me.owner,
      doc = Ext.getDoc(),
      oldCard = me.activeItem,
      newIndex;
   animation = (animation == undefined) ? this.getAnimation(newCard, owner) : animation;
   var hideActive = hideActive == undefined ? false : hideActive;
   newCard = me.parseActiveItem(newCard);
   newIndex = owner.items.indexOf(newCard);
   // If the card is not a child of the owner, then add it
   if (newIndex == -1) {
      owner.add(newCard);
   }
   // Is this a valid, different card?
   if (newCard &amp;&amp; oldCard != newCard &amp;&amp; owner.onBeforeCardSwitch(newCard, oldCard,             newIndex, !!animation) !== false) {
      // If the card has not been rendered yet, now is the time to do so.
      if (!newCard.rendered) {
         this.layout();
      }
      // Fire the beforeactivate and beforedeactivate events on the cards
      if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
         return false;
      }
      if (oldCard &amp;&amp; oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
         return false;
      }
      // Make sure the new card is shown, but only show if not explictly prohibited
      if (newCard.hidden<strong> &amp;&amp; !hideActive</strong>) {
         newCard.show();
      }
      me.activeItem = newCard;
      if (animation) {
         doc.on('click', Ext.emptyFn, me, {
            single: true,
            preventDefault: true
         });
         Ext.Anim.run(newCard, animation, {
            out: false,
            autoClear: true,
            scope: me,
            after: function() {
               Ext.defer(function() {
                  doc.un('click', Ext.emptyFn, me);
               },
               50, me);

               newCard.fireEvent('activate', newCard, oldCard);

               if (!oldCard) {
                  // If there is no old card, the we have to make sure that we fire
                  // onCardSwitch here.
                  owner.onCardSwitch(newCard, oldCard, newIndex, true);
               }
            }
         });
         if (oldCard) {
            Ext.Anim.run(oldCard, animation, {
               out: true,
               autoClear: true,
               after: function() {
                  oldCard.fireEvent('deactivate', oldCard, newCard);
                  if (me.hideInactive &amp;&amp; me.activeItem != oldCard) {
                     oldCard.hide();
                  }
                  // We fire onCardSwitch in the after of the oldCard animation
                  // because that is the last one to fire, and we want to make sure
                  // both animations are finished before firing it.
                  owner.onCardSwitch(newCard, oldCard, newIndex, true);
               }
            });
         }
      }
      else {
         newCard.fireEvent('activate', newCard, oldCard);
         if (oldCard) {
            oldCard.fireEvent('deactivate', oldCard, newCard);
            if (me.hideInactive) {
               oldCard.hide();
            }
         }
         owner.onCardSwitch(newCard, oldCard, newIndex, false);
      }
      return newCard;
   }
      return false;
   }
})</pre>
<h2>Wrapping Up</h2>
<p>And that&#8217;s about it. I think the final solution is fairly straightforward, and provides what I think is missing functionality within the NestedList. If you think I&#8217;ve missed something, or could accomplish parts of this in better or more efficient ways, please let me know&#8211;I&#8217;d love any and all feedback on this. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://existdissolve.com/2011/09/sencha-touch-jumptonode-and-the-nestedlist/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

