<?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>SwarmOnline &#187; Web Design &amp; Development Blog</title>
	<atom:link href="http://www.swarmonline.com/category/web-design-development-blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.swarmonline.com</link>
	<description></description>
	<lastBuildDate>Tue, 21 May 2013 02:26:01 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>PhoneGap and the TestFlight SDK &#8211; Taking it Further!</title>
		<link>http://www.swarmonline.com/2013/05/phonegap-and-the-testflight-sdk-taking-it-further/</link>
		<comments>http://www.swarmonline.com/2013/05/phonegap-and-the-testflight-sdk-taking-it-further/#comments</comments>
		<pubDate>Tue, 21 May 2013 02:20:18 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Development Tips]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1906</guid>
		<description><![CDATA[In our last post on TestFlight and PhoneGap we talked about how to integrate the TestFlight SDK [...]]]></description>
				<content:encoded><![CDATA[<h1><span style="font-size: 13px;">In our </span><a style="font-size: 13px;" href="http://www.swarmonline.com/2013/05/integrating-the-testflight-sdk-into-your-phonegap-application/">last post on TestFlight and PhoneGap</a><span style="font-size: 13px;"> we talked about how to integrate the TestFlight SDK into a PhoneGap project using the </span><a style="font-size: 13px;" href="https://github.com/shazron/TestFlightPlugin">TestFlight Plugin</a><span style="font-size: 13px;">. In this article we are going to show you how to take advantage of more of the SDK&#8217;s features including logging, collecting feedback, asking questions and customising the environment data saved.</span></h1>
<p><span id="more-1906"></span></p>
<h2>Sample Code</h2>
<p>We are going to build on the sample project we created in <a href="http://www.swarmonline.com/2013/05/integrating-the-testflight-sdk-into-your-phonegap-application/">part one</a> so if you haven&#8217;t already, grab a copy from the <a href="https://github.com/SwarmOnline/TestFlightPhoneGapTutorial">GitHub repository</a>. The code from this article can be found in the &#8220;<a href="https://github.com/SwarmOnline/TestFlightPhoneGapTutorial/tree/TakingItFurther" target="_blank">TakingItFurther</a>&#8221; branch.</p>
<p><strong>NOTE: To try this code you will need a TestFlight account and upload a new build of the sample application to TestFlight in order to try out each new feature.</strong></p>
<h2>Custom Environment Information</h2>
<p>When you track a user&#8217;s session with the TestFlight SDK it automatically collects various bits of information about the user&#8217;s device and setup. The image below shows this information from my phone when using our test application.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/01-DeviceEnvironmentInfo.png"><img class="size-medium wp-image-1908 aligncenter" alt="01-DeviceEnvironmentInfo" src="http://www.swarmonline.com/wp-content/uploads/2013/05/01-DeviceEnvironmentInfo-202x300.png" width="202" height="300" /></a></p>
<p>This collects a lot of details and you probably see everything you might need on that list but TestFlight allows us to grab as many other bits of information we are want and add them to this list.</p>
<p>We use the <code>addCustomEnvironmentInformation</code> method of our TestFlight object to add a name/value pair to the environment information. This data will then be sent up to TestFlight when we &#8216;take off&#8217;.</p>
<p>If you add the following code snippet to your <code>onDeviceReady</code> method, right after the <code>setDeviceIdentifier</code> call, we will add an environment variable named &#8220;My Environment Variable&#8221; with a value of &#8220;Some environment info&#8221;. As usual the method accepts success and failure callback methods as the first two parameters.</p>
<pre><code>TF.addCustomEnvironmentInformation(function(){
    console.log('Add Custom Environment Info Success');
}, function(){
    console.log('Add Custom Environment Info Failure');
}, 'My Environment Variable', 'Some environment info');
</code></pre>
<p>By adding this code and starting a new session, we will see our new variable added to the Session Details screen.</p>
<p style="text-align: center;"><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/02-CustomDeviceEnvironmentInfo.png"><img class="alignnone size-medium wp-image-1912" alt="02-CustomDeviceEnvironmentInfo" src="http://www.swarmonline.com/wp-content/uploads/2013/05/02-CustomDeviceEnvironmentInfo-183x300.png" width="183" height="300" /></a></p>
<p>Please note that these calls should be made <strong>before</strong> &#8216;take off&#8217;.</p>
<h2>Remote Logging</h2>
<p>In our application we are performing several <code>console.logs</code> at various points to indicate what is happening in our code. This is great for when we are testing in the browser and when debugging on a device via xCode but this information isn&#8217;t available once the app is loose on testers&#8217; devices. The TestFlight SDK offers a remote logging mechanism that will send up logging strings and attach them to the user&#8217;s session. You can then browse these items and see what happened during the session.</p>
<p>We will add a simple logging message when we have successfully completed our &#8216;take off&#8217;. We add the following code into the callback function of the <code>takeOff</code> call, passing in success and failure callback functions and the string we would like to log.</p>
<pre><code>TF.remoteLog(function(){
    console.log('Remote Log Success');
}, function(){
    console.log('Remote Log Failure');
}, 'Take Off Success');
</code></pre>
<p>It is important to note that logging can only be done <strong>after</strong> &#8220;take off&#8221; which is when the session starts.</p>
<p>On the TestFlight website we can browse the logs that have been made during a session by clicking the &#8220;Sessions&#8221; item on the left hand menu and then clicking the blue &#8220;i&#8221; icon beside the relevant Session (you may have to click the user&#8217;s row to expand the Sessions if they have more than one). On the modal window that appears you must use the dropdown menu at the top right to display the log messages. The Log record will show all the auto-generated log messages (such as Checkpoints and internal logs) as well as your custom ones.</p>
<p style="text-align: center;"><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/03-RemoteLogging.png"><img class="alignnone size-large wp-image-1913" alt="03-RemoteLogging" src="http://www.swarmonline.com/wp-content/uploads/2013/05/03-RemoteLogging-1024x298.png" width="640" height="186" /></a></p>
<h2>Collecting Feedback</h2>
<p>The TestFlight SDK makes it very easy for us to collect feedback from our users at any point within our application. The <code>openFeedbackView</code> method will open a native form, overlaying our application, which allows the user to enter some text that, when submitted, will be attached to the build for viewing on the website and also emailed to you.</p>
<p style="text-align: center;"><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/04-FeedbackForm.png"><img class="alignnone size-medium wp-image-1909" alt="04-FeedbackForm" src="http://www.swarmonline.com/wp-content/uploads/2013/05/04-FeedbackForm-208x300.png" width="208" height="300" /></a></p>
<p>We will add another link to our app that will show this view and collect feedback from the user. You might prefer to have the form automatically appear when the user completes an action in your application, for example, after updating their profile, ask them how easy it was.</p>
<p>The following HTML is added below our existing links:</p>
<pre><code>&lt;a href="#" onclick="doOpenFeedback()"&gt;Submit Feedback&lt;/a&gt;
</code></pre>
<p>We then add the <code>doOpenFeedback</code> function inside our JavaScript tags:</p>
<pre><code>function doOpenFeedback(){
    console.log('Opening Feedback');
    // Open the TestFlight SDK's feedback form
    TF.openFeedbackView(function(){
        console.log('Feedback Callback Success');
    }, function(){
        console.log('Feedback Callback Failure')
    });
}
</code></pre>
<p>Once again we pass in success and failure callback functions but that is all we need to add &#8211; the SDK takes care of the submission.</p>
<p>You can view all feedback received from a build on the TestFlight website by clicking the &#8220;Feedback&#8221; link in the left hand menu.</p>
<h2>Custom Feedback Submission</h2>
<p>Although the previous technique for collecting feedback is very easy, it might not be versatile enough for those who want to collect more in-depth feedback. To address this we can use the <code>submitFeedback</code> method which allows us to collect our own feedback string and submit it ourselves.</p>
<p>We are going to demonstrate this by creating a small feedback form with a textarea and a select field. We add this to the bottom of our HTML document.</p>
<pre><code>&lt;div id="customFeedback" style="display: none;"&gt;
    &lt;h1&gt;Custom Feedback&lt;/h1&gt;
    &lt;label for="feedback"&gt;Feedback&lt;/label&gt;
    &lt;br/&gt;
    &lt;textarea id="feedback"&gt;&lt;/textarea&gt;
    &lt;br/&gt;&lt;br/&gt;
    &lt;label for="rating"&gt;Rating&lt;/label&gt;
    &lt;br/&gt;
    &lt;select id="rating"&gt;
        &lt;option value="1"&gt;1&lt;/option&gt;
        &lt;option value="2"&gt;2&lt;/option&gt;
        &lt;option value="3"&gt;3&lt;/option&gt;
        &lt;option value="4"&gt;4&lt;/option&gt;
        &lt;option value="5"&gt;5&lt;/option&gt;
    &lt;/select&gt;
    &lt;br/&gt;&lt;br/&gt;
    &lt;button onclick="submitCustomFeedback()"&gt;Submit&lt;/button&gt;
&lt;/div&gt;
</code></pre>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/05-CustomFeedbackForm.png"><img class="size-medium wp-image-1910 aligncenter" style="border: 1px solid #484848;" alt="05-CustomFeedbackForm" src="http://www.swarmonline.com/wp-content/uploads/2013/05/05-CustomFeedbackForm-208x300.png" width="208" height="300" /></a></p>
<p>When tapped, the Submit button will execute the <code>submitCustomFeedback</code> method which will collect the data from the form and pass it to the SDK&#8217;s <code>submitFeedback</code> method. The following code does this:</p>
<pre><code>function submitCustomFeedback(){
    console.log('Submitting Custom Feedback');
    // Get references to our form and fields, and build our feedback string
    var feedbackForm    = document.querySelectorAll('#customFeedback')[0],
        feedbackField   = document.querySelectorAll('#feedback')[0],
        ratingField     = document.querySelectorAll('#rating')[0],
        feedbackString  = 'Feedback: ' + feedbackField.value + '. Rating: ' + ratingField.value;
    // hide the form
    feedbackForm.style.display = 'none';
    // Submit our custom feedback string
    TF.submitFeedback(function(){
        console.log('Custom Feedback Submit Success');
    }, function(){
        console.log('Custom Feedback Submit Failure');
    }, feedbackString);
}
</code></pre>
<p>This short function will grab references to the form and its fields, then use the fields&#8217; values to create a feedback string. The feedback string is then passed to the SDK&#8217;s <code>submitFeedback</code> method as its third parameter (the first and second being success and failure callback functions respectively).</p>
<p>In order for the form to be shown we add another link to our app that will show the form&#8217;s DIV.</p>
<pre><code>&lt;a href="#" onclick="doCustomFeedback()"&gt;Custom Feedback&lt;/a&gt;
</code></pre>
<p>The <code>doCustomFeedback</code> function simply gets a reference to the form and toggles its <code>display</code> property.</p>
<pre><code>function doCustomFeedback(){
    console.log('Opening Custom Feedback');
    var feedbackForm = document.querySelectorAll('#customFeedback')[0];
    if(feedbackForm.style.display === 'none'){
        feedbackForm.style.display = 'block';
    } else {
        feedbackForm.style.display = 'none';
    }
}
</code></pre>
<p>The feedback submitted through this method will be dealt with in the same way as feedback submitted using the built-in form.</p>
<h2>Collecting User Feedback with Questions</h2>
<p>The TestFlight SDK allows us to attach questions to each of our defined Checkpoints that allows us to collect specific information from users. This is an alternative to creating your own custom feedback form like we did in the previous section but it is important to note the difference in the way the collected data is handled.</p>
<p>Questions are defined and attached to a build after it has been uploaded to TestFlight and are attached to the Checkpoints that the app knows about.</p>
<p>In our app we will add a question to our &#8220;Awesome Feature 2&#8243; Checkpoint. We log into TestFlight and navigate to our latest build. We then click the &#8220;Questions&#8221; link at the bottom of the left hand menu.</p>
<p style="text-align: center;"><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/06-QuestionsList.png"><img class="alignnone size-large wp-image-1914" alt="06-QuestionsList" src="http://www.swarmonline.com/wp-content/uploads/2013/05/06-QuestionsList-1024x411.png" width="640" height="256" /></a></p>
<p>Click the &#8220;Add Question&#8221; button and a form is shown where we define our question. Questions can have 3 formats: Yes/No, Multiple Choice or Long Answer. We are going to create a very simple Yes/No question (shown below) and attach it to the &#8220;Awesome Feature 2&#8243; Checkpoint.</p>
<p style="text-align: center;"><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/07-QuestionDefinition.png"><img class="alignnone size-large wp-image-1915" alt="07-QuestionDefinition" src="http://www.swarmonline.com/wp-content/uploads/2013/05/07-QuestionDefinition-1024x395.png" width="640" height="246" /></a></p>
<p>After clicking Save we see our question in the list and the fact it has zero answers. If we now launch our application on our device (you will need to quit and then restart the app first) and tap the &#8220;Awesome Feature 2&#8243; link we will be presented with a new view containing our question.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/09-QuestionForm.png"><img class="size-medium wp-image-1911 aligncenter" alt="09-QuestionForm" src="http://www.swarmonline.com/wp-content/uploads/2013/05/09-QuestionForm-208x300.png" width="208" height="300" /></a></p>
<p>If we answer the question with &#8220;Yes&#8221; (of course…) then we can refresh our dashboard screen and see the response being logged.</p>
<h2>Summary</h2>
<p>This has been a quick rundown of the more advanced features of the TestFlight SDK that are made very easy to integrate using the PhoneGap plugin. You should now be able to perform Remote Logging; collect Feedback using the built-in form and a custom HTML form; track Custom Environment Information and prompt users to answer Questions about a specific Checkpoint they have just passed. Not bad!</p>
<p>Let me know if you have any questions or comments below!</p>]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2013/05/phonegap-and-the-testflight-sdk-taking-it-further/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrating the TestFlight SDK into your PhoneGap Application</title>
		<link>http://www.swarmonline.com/2013/05/integrating-the-testflight-sdk-into-your-phonegap-application/</link>
		<comments>http://www.swarmonline.com/2013/05/integrating-the-testflight-sdk-into-your-phonegap-application/#comments</comments>
		<pubDate>Mon, 20 May 2013 00:48:31 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Development Tips]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1870</guid>
		<description><![CDATA[This tutorial covers how we go about integrating TestFlight&#8217;s (www.testflightapp.com) SDK into your PhoneGap (aka Cordova) iOS [...]]]></description>
				<content:encoded><![CDATA[<h1><span style="font-size: 13px;">This tutorial covers how we go about integrating TestFlight&#8217;s (<a title="TestFlight App" href="http://www.testflightapp.com" target="_blank">www.testflightapp.com</a>) SDK into your PhoneGap (aka Cordova) iOS application. If you don&#8217;t know about TestFlight yet I suggest you head over there right now and sign up &#8211; it is an invaluable way of distributing and managing your iOS (and soon Android!) applications and builds. And did I mention it&#8217;s completely free? You will need an account to complete this tutorial so get down there now!</span></h1>
<p><span id="more-1870"></span></p>
<h2>Supporting Code</h2>
<p>All the code that we create in this tutorial can be found on our <a href="https://github.com/SwarmOnline/TestFlightPhoneGapTutorial">GitHub</a> account so you can grab it from there and reference it as you follow if you prefer.</p>
<h2>Create a Blank iOS Project</h2>
<p>We&#8217;re going to create a blank iOS PhoneGap project to work with in this tutorial but if you already have a project you want to integrate the plugin with then you can skip ahead to the next step.</p>
<p>We start by creating a new project folder somewhere on your hard drive &#8211; I&#8217;m going to create one called &#8220;TestFlightPG&#8221;.</p>
<p>Next we&#8217;re going to download the latest version of <a href="http://www.phonegap.com/download">PhoneGap</a> and paste a copy into our project folder. We are doing this purely for convenience when it comes to commands so if you&#8217;re comfortable modifying the next commands to reference the PhoneGap folder somewhere else then go for it!</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/01-PhoneGapInFolder.png"><img class="size-large wp-image-1877 aligncenter" alt="01-PhoneGapInFolder" src="http://www.swarmonline.com/wp-content/uploads/2013/05/01-PhoneGapInFolder-1024x136.png" width="640" height="85" /></a></p>
<p>With that in place we can create our iOS project. PhoneGap comes with some nifty command line tools for getting us up and running extremely quickly by creating an iOS project with everything set up already. We create our project by opening up a Terminal window and &#8220;cd&#8221;ing to our &#8220;TestFlightPG&#8221;" folder. In my case the command is:</p>
<pre><code>cd Workspace/TestFlightPG
</code></pre>
<p>Now we&#8217;re in the right place we run the following command to create our blank project:</p>
<pre><code>PhoneGap2.7/lib/ios/bin/create iOS com.SwarmOnline.TestFlightPG TestFlightPG
</code></pre>
<p>This will call the iOS <strong>create</strong> command which will create a new folder called <strong>iOS</strong> and generate an iOS project named <strong>TestFlightPG</strong> in that folder with the identifier <strong>com.SwarmOnline.TestFlightPG</strong>. Easy!</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/02-GeneratediOSProject.png"><img class="size-large wp-image-1878 aligncenter" alt="02-GeneratediOSProject" src="http://www.swarmonline.com/wp-content/uploads/2013/05/02-GeneratediOSProject-1024x526.png" width="640" height="328" /></a></p>
<h2>Integrating the TestFlight Plugin</h2>
<p>Before we can integrate the plugin we need to grab a copy of it from its GitHub repository. It is currenly hosted outside of the usual PhoneGap Plugins repo &#8211; (<a href="https://github.com/shazron/TestFlightPlugin">https://github.com/shazron/TestFlightPlugin</a>). Either clone the repository or download the <a href="https://github.com/shazron/TestFlightPlugin/archive/master.zip">ZIP archive</a> and then move this folder into our <strong>TestFlightPG</strong> project folder. We should have something like this:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/03-TestFlightPlugin.png"><img class="size-large wp-image-1879 aligncenter" alt="03-TestFlightPlugin" src="http://www.swarmonline.com/wp-content/uploads/2013/05/03-TestFlightPlugin-1024x323.png" width="640" height="201" /></a></p>
<h3>Adding TestFlight SDK</h3>
<p>Now that we have a new project and the plugin code, we need to open the project in xCode, where we see a blank PhoneGap project.</p>
<p>Fortunately, the plugin already contains the latest TestFlight SDK code (1.2 as of writing) so our first step is to copy this into our project.</p>
<p>We start by creating a new group under the TestFlightPG heading and name it <strong>TestFlight</strong>. We do this by right clicking the TestFlightPG heading and choosing &#8220;Create Group&#8221;.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/04-NewTestFlightGroup.png"><img class="size-large wp-image-1872 aligncenter" alt="04-NewTestFlightGroup" src="http://www.swarmonline.com/wp-content/uploads/2013/05/04-NewTestFlightGroup-1024x508.png" width="640" height="317" /></a></p>
<p>Next we add the TestFlight SDK files into our new group by right clicking it and choosing &#8220;Add Files to TestFlightPG…&#8221;. We navigate to the TestFlightPlugin folder inside our parent project folder and find the <strong>libTestFlight.a</strong> and <strong>TestFlight.h</strong> files inside the &#8220;src/ios&#8221; folder. Make sure you tick the &#8220;Copy items into destination group&#8217;s folder&#8221; option so the files get moved into our project.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/05-AddTestFlightSDKFiles.png"><img class="size-large wp-image-1873 aligncenter" alt="05-AddTestFlightSDKFiles" src="http://www.swarmonline.com/wp-content/uploads/2013/05/05-AddTestFlightSDKFiles-1024x686.png" width="640" height="428" /></a></p>
<h3>Adding TestFlight Plugin Code</h3>
<p>Our next step is to add the PhoneGap plugin files into the project. We follow a similar process as above by creating a new Group inside the <strong>Plugins</strong> group and naming it <strong>TestFlight</strong>.</p>
<p>We can then right click it and choose the &#8220;Add Files to TestFlightPG…&#8221; option. In the file chooser, we add the other two files from the &#8220;src/ios&#8221; folder &#8211; <strong>CDVTestFlight.h</strong> and <strong>CDVTestFlight.m</strong>. Once again, we make sure the &#8220;Copy items into destination group&#8217;s folder&#8221; option is ticked.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/06-AddTestFlightPlugin.png"><img class="size-large wp-image-1880 aligncenter" alt="06-AddTestFlightPlugin" src="http://www.swarmonline.com/wp-content/uploads/2013/05/06-AddTestFlightPlugin-1024x727.png" width="640" height="454" /></a></p>
<p>Once we have done this we should have a project that looks similar to the following:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/07-ProjectAfterImports.png"><img class="size-medium wp-image-1881 aligncenter" alt="07-ProjectAfterImports" src="http://www.swarmonline.com/wp-content/uploads/2013/05/07-ProjectAfterImports-182x300.png" width="182" height="300" /></a></p>
<h3>Adding Library References</h3>
<p>Once this has been done we need to add a reference to a library called <strong>libz.dylib</strong>. We do this by selecting our <strong>TestFlightPG</strong> &#8220;Target&#8221; and then clicking the <strong>Build Phases</strong> tab. We then expand the &#8220;Link Binary with Libraries&#8221; section. You should be seeing something similar to the screenshot below:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/08-AddingLibrary.png"><img class="size-large wp-image-1882 aligncenter" alt="08-AddingLibrary" src="http://www.swarmonline.com/wp-content/uploads/2013/05/08-AddingLibrary-1024x835.png" width="640" height="521" /></a></p>
<p>We add the library by clicking the &#8220;+&#8221; button at the lower left of the section and then filtering the list by typing in the library name.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/09-LibraryFilterList.png"><img class="size-medium wp-image-1883 aligncenter" alt="09-LibraryFilterList" src="http://www.swarmonline.com/wp-content/uploads/2013/05/09-LibraryFilterList-259x300.png" width="259" height="300" /></a></p>
<p>You can then select the last option (the one without any version numbers) and click &#8220;Add&#8221;.</p>
<h3>Updating Config.xml</h3>
<p>The final step in integrating the plugin is to update the config.xml file which holds all the PhoneGap configuration. We must add two things:</p>
<p>First we must reference the TestFlight plugin so it is initialised correctly. We do this by adding the following line inside &lt;plugins&gt; tags.</p>
<pre><code>&lt;plugin name="TestFlightSDK" value="CDVTestFlight" /&gt;
</code></pre>
<p>Secondly, we update the external hosts whitelist to allow calls to all &#8220;testflightapp.com&#8221; domains. In our example we have a wildcard set up so we don&#8217;t need to do this but if you are integrating into an existing app then add the following line to your config.xml.</p>
<pre><code>&lt;access origin="*.testflightapp.com" /&gt;
</code></pre>
<p>Our final config.xml should look like this:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/10-ConfigXML.png"><img class="size-large wp-image-1874 aligncenter" alt="10-ConfigXML" src="http://www.swarmonline.com/wp-content/uploads/2013/05/10-ConfigXML-770x1024.png" width="640" height="851" /></a></p>
<p>We have now integrated the TestFlight SDK and the PhoneGap plugin into our project, so now all that&#8217;s left is to set up our JavaScript so we can start using it.</p>
<h2>Adding and Configuring the TestFlight Plugin&#8217;s JavaScript</h2>
<p>This section is going to focus on how we set up and interact with the TestFlight plugin from our app&#8217;s JavaScript.</p>
<h3>Creating our Test &#8220;App&#8221;</h3>
<p>In our blank PhoneGap project we are given a sample web app (inside the <strong>www</strong> folder) &#8211; we&#8217;re going to go ahead and remove all these files apart from the <strong>index.html</strong> and <strong>cordova-2.7.0.js</strong>.</p>
<p>W&#8217;re going to replace the contents of the <strong>index.html</strong> with the following code. We want to have a very simple page that references the Cordova (nee PhoneGap) JavaScript file and adds a handler to the <strong>deviceready</strong> event (which will log a message to the console). This event fires when PhoneGap has sorted itself out and all of its interfaces are available for us to interact with.</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;TestFlightPG&lt;/title&gt;
        &lt;script type="text/javascript" src="cordova-2.7.0.js"&gt;&lt;/script&gt;
        &lt;script type="text/javascript"&gt;
            document.addEventListener('deviceready', onDeviceReady, false);
            function onDeviceReady() {
                console.log('Device Ready');
            }
        &lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h3>Add the TestFlight Plugin&#8217;s JavaScript Script</h3>
<p>Just like PhoneGap itself, the TestFlight plugin has its own JavaScript script which gives us a nice interface to interact with the plugin&#8217;s native code. We import the file (<strong>testflight.js</strong>) from the &#8220;TestFlightPlugin/www&#8221; folder we added to our project earlier, into our own &#8220;www&#8221; folder.</p>
<p>We can then add a reference to this new script in our HTML page after the one for the Cordova script.</p>
<pre><code>&lt;script type="text/javascript" src="testflight.js"&gt;&lt;/script&gt;
</code></pre>
<p>This now means once that the &#8220;deviceready&#8221; event fires we can start interacting with the TestFlight plugin.</p>
<h3>Requiring the Plugin</h3>
<p>The first thing we must do is &#8220;require&#8221; the TestFlightPlugin so it gets loaded up and we have an object to work with throughout our codebase. We do this by simply adding the following line to our <strong>onDeviceReady</strong> method.</p>
<pre><code>window.TF = cordova.require("cordova/plugin/testflightsdk");
</code></pre>
<p>We assign the output of this <strong>cordova.require</strong> call in a global variable name <strong>TF</strong>. We do this so we can reference it anywhere in our code.</p>
<h3>Identifying the User</h3>
<p>Now we have a global reference to the initialised plugin we start by identifying the user. The SDK no longer uses the device&#8217;s UUID, so in order to allow identification of a user&#8217;s data we must provide an ID &#8211; in your own application you might wait until login and use the user&#8217;s Username or UserID. In our case we&#8217;re going to use the UUID provided by PhoneGap &#8211; it&#8217;s not ideal but serves the purpose here.</p>
<p>So after the <strong>require</strong> call we call the <strong>setDeviceIdentifier</strong> method passing in a success callback function, a failure callback function and the ID itself.</p>
<pre><code>TF.setDeviceIdentifier(function(){
    console.log('Device Identify Success');
}, function(){
    console.log('Device Identify Fail');
}, window.device.uuid);
</code></pre>
<p>We just log a message on success/failure but you can do something more interesting, or just pass in an empty function.</p>
<p>At this point our <strong>onDeviceReady</strong> function should look like this and if we launch our app we should see a blank screen and our two console logs in the output window (among others).</p>
<pre><code>function onDeviceReady() {
    console.log('Device Ready');
    // Require the TestFlight SDK
    window.TF = cordova.require("cordova/plugin/testflightsdk");
    // Identify the current Device
    TF.setDeviceIdentifier(function(){
        console.log('Device Identify Success');
    }, function(){
        console.log('Device Identify Fail');
    }, window.device.uuid);
}
</code></pre>
<h3><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/11-IdentifySuccessOutput.png"><img class="size-medium wp-image-1875 aligncenter" alt="11-IdentifySuccessOutput" src="http://www.swarmonline.com/wp-content/uploads/2013/05/11-IdentifySuccessOutput-300x207.png" width="300" height="207" /></a></h3>
<h3>Ready for TakeOff?</h3>
<p>Inkeeping with the aeronautical theme of TestFlight we start the SDK&#8217;s tracking session by using the <strong>takeOff</strong> method. Into this we pass the standard success and failure callback functions and also your TestFlight Application&#8217;s App Token. This token is used to hook up the SDK to your account &#8211; we&#8217;ll explain where to get that in a moment.</p>
<p>First, let&#8217;s add this <strong>takeOff</strong> call to our <strong>onDeviceReady</strong>:</p>
<pre><code>TF.takeOff(function(){
    console.log('Take Off Success');
}, function(){
    console.log('Take Off Fail');
}, '&lt;TEST FLIGHT APP TOKEN&gt;');
</code></pre>
<p>Interestingly, if you run your app now, the success callback will be executed but we also get an error alerting us that the App Token is incorrect. Which it is.</p>
<h3>Finding your Application Token</h3>
<p>Before we can go any further we need to locate your TestFlight Application Token &#8211; I&#8217;m going to assume you already have a TestFlight account so fire up your browser and navigate to <a href="http://testflightapp.com">TestFlightApp.com</a> and login.</p>
<p>Navigate to your App by clicking on the <strong>Apps</strong> link on the main navigation bar, then click your app&#8217;s name from the list &#8211; in our case the app is called &#8220;TestFlightPG&#8221;.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/12-TFManageApps.png"><img class="size-large wp-image-1876 aligncenter" alt="12-TFManageApps" src="http://www.swarmonline.com/wp-content/uploads/2013/05/12-TFManageApps-1024x373.png" width="640" height="233" /></a></p>
<p>On the following screen you need to click the cunningly named <strong>App Token</strong> item on the left menu so you get a screen like this:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/13-TFAppToken.png"><img class="size-large wp-image-1884 aligncenter" alt="13-TFAppToken" src="http://www.swarmonline.com/wp-content/uploads/2013/05/13-TFAppToken-1024x485.png" width="640" height="303" /></a></p>
<p>The big string in the middle is the token we are after, so go ahead and copy and paste it into our <strong>takeOff</strong> call.</p>
<p>Now let&#8217;s launch our app in xCode and see how far we get this time! We should now see a more encouraging message in the output saying our App Token has been recognized. Yaldi!</p>
<h3>Adding Checkpoints</h3>
<p>So now we&#8217;re at the step we all wanted to be at the start… tracking user interactions. We&#8217;ll start by adding a couple of links to our page to represent our app&#8217;s actions and bind them to an onclick handler &#8211; inline… I know, old-school!</p>
<p>Fire the following code into your &lt;BODY&gt;:</p>
<pre><code>&lt;a onclick="doTrackLink('Awesome Feature 1')"&gt;Awesome Feature 1&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;a onclick="doTrackLink('Awesome Feature 2')"&gt;Awesome Feature 2&lt;/a&gt;
</code></pre>
<p>and this JavaScript function into our &lt;SCRIPT&gt; tag:</p>
<pre><code>function doTrackLink(name){
    console.log('Tracking Link: ' + name);
}
</code></pre>
<p>Launching the app now and tapping our two links should see them being logged to the console output &#8211; all&#8217;s working nicely (see things <em>can</em> work without jQuery or Sencha <img src='http://www.swarmonline.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ).</p>
<p>Now we add in our call to send the checkpoint to the TestFlight SDK &#8211; we use the <strong>passCheckpoint</strong> method which accepts a success and failure callback and a string that will be used as the checkpoint&#8217;s identifier. TestFlight will group and count checkpoint passes by this identifier so make it unique and human readable so you can understand your stats!</p>
<p>Add the following code to the <strong>doTrackLink</strong> method:</p>
<pre><code>TF.passCheckpoint(function(){
    console.log('Pass Checkpoint Success');
}, function(){
    console.log('Pass Checkpoint Fail');
}, name);
</code></pre>
<p>When we run our app now and click some links we should get some nice noises coming back from TestFlight &#8211; our checkpoints are working!</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/14-CheckpointConsoleOutput.png"><img class="size-medium wp-image-1885 aligncenter" alt="14-CheckpointConsoleOutput" src="http://www.swarmonline.com/wp-content/uploads/2013/05/14-CheckpointConsoleOutput-300x202.png" width="300" height="202" /></a></p>
<h2>Viewing our Checkpoints</h2>
<p>Having our app log checkpoints is all well and good but if we can&#8217;t see the data it&#8217;s no use, right? Fortunately, TestFlight has created a neat little tool to allow us to view our SDK interactions in real-time and verfiy that things are working correctly and the SDK is <em>really</em> receiving our calls.</p>
<p>The SDK Debugger can be accessed via the link named &#8220;SDK Debugger&#8221; just under the &#8220;App Token&#8221; link we used earlier. When you get there you will see an Events list and a couple of action buttons.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/05/15-SDKDebugger.png"><img class="size-large wp-image-1886 aligncenter" alt="15-SDKDebugger" src="http://www.swarmonline.com/wp-content/uploads/2013/05/15-SDKDebugger-1024x313.png" width="640" height="195" /></a></p>
<p>If we launch our app and start clicking on the links we should be able to go back to the SDK Debugger and see these events coming up with various details about the device etc. Noice!</p>
<p>At this point you won&#8217;t see any stats inside the TestFlight Live dashboard &#8211; stats will only here once a build has been properly submitted to TestFlight.</p>
<h2>Summary</h2>
<p>So by now we should have the TestFlight SDK integrated with our iOS PhoneGap application (via the TestFlight PhoneGap plugin) and have it hooked up to our TestFlight account and recording checkpoint markers.</p>
<p>We are going to make this into a mini-series of posts and next time will look at some of the other features (over and above Checkpoints) that the TestFlight SDK has to offer. We will then look at integrating it neatly with a Sencha Touch application.</p>
<p>Keep checking back for updates and as always let us know if you have any questions or comments in the comments area below!</p>
<p><a title="PhoneGap and the TeestFlight SDK - Taking it Further" href="http://www.swarmonline.com/2013/05/phonegap-and-the-testflight-sdk-taking-it-further">PhoneGap and the TestFlight SDK &#8211; Taking if Further</a>, the second part of this mini-series, is available now!</p>]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2013/05/integrating-the-testflight-sdk-into-your-phonegap-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Retrieving References to Internal View Components</title>
		<link>http://www.swarmonline.com/2013/05/retrieving-references-to-internal-view-components/</link>
		<comments>http://www.swarmonline.com/2013/05/retrieving-references-to-internal-view-components/#comments</comments>
		<pubDate>Mon, 20 May 2013 00:45:03 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Development Tips]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1891</guid>
		<description><![CDATA[The Problem When adding logic to Sencha Touch views we often need to grab references to internal [...]]]></description>
				<content:encoded><![CDATA[<h2>The Problem</h2>
<p>When adding logic to Sencha Touch views we often need to grab references to internal Components to manipulate them.</p>
<p>We find ourselves having to either cache a reference to items by creating them individually or adding getter methods that performed a ComponentQuery or that delved into the items collection.</p>
<p><span id="more-1891"></span></p>
<p>The code below shows these techniques in a sample component:</p>
<pre><code>Ext.define('MyContainer', {
    extend: 'Ext.Container',
    config: {
        items: [
            {
                xtype: 'component',
                itemId: 'myComponent',
                html: 'My Component'
            },
            {
                xtype: 'component',
                itemId: 'myOtherComponent',
                html: 'My Other Component'
            }
        ]
    },
    initialize: function(){
        this.callParent(arguments);
        this.myButton = Ext.create('Ext.Button', {
            text: 'My Button'
        });
        this.add(this.myButton);
    },
    getMyComponent: function(){
        return this.query('#myComponent')[0];
    },
    getMyOtherComponent: function(){
        return this.getItems().getAt(1);
    }
});
</code></pre>
<h2>The Solution</h2>
<p>This override allows you to define quick references, based on ComponentQueries, to the Components in a view, like you would in a Controller, so that the references to those components exist in the view automatically.</p>
<p>We use this override by adding a <strong>refs</strong> property to your view&#8217;s definition and giving it an object literal where each key is the property the reference will be assigned to and the value, a Component Query that is used to target it.</p>
<p>Our previous example could be rewritten as follows:</p>
<pre><code>Ext.define('MyContainer', {
    extend: 'Ext.Container',
    refs: {
        myComponent     : '#myComponent',
        myOtherComponent: '#myOtherComponent',
        myButton        : 'button'
    },
    config: {
        items: [
            {
                xtype: 'component',
                itemId: 'myComponent',
                html: 'My Component'
            },
            {
                xtype: 'component',
                itemId: 'myOtherComponent',
                html: 'My Other Component'
            },
            {
                xtype: 'button',
                text: 'My Button'
            }
        ]
    },
    initialize: function(){
        this.callParent(arguments);
        // reference components using the new properties
        // this.myComponent
        // this.myOtherComponent
        // this.myButton
    }
});
</code></pre>
<p>This technique saves us few lines of code and makes things a little tidier for us to code against.</p>
<h2>The Override</h2>
<p>The override adds a new method called <strong>processRefs</strong> to the <strong>Ext.Container</strong> class which iterates over each item in the <strong>refs</strong> property, executing its Component Query and assigning the <em>first</em> result to a property with the name you gave it in your config.</p>
<p>This <strong>processRefs</strong> called in an override of the <strong>applyItems</strong> method.</p>
<p>The full override code can be seen below:</p>
<pre><code>Ext.define('Ext.overrides.Container', {
    override: 'Ext.Container',
    applyItems: function(items, collection){
        var returnVal = this.callOverridden(arguments);
        this.processRefs();
        return returnVal;
    },
    /**
     * Iterates over the 'refs' property performing each query and assigning its result
     * to a property with the right name.
     * @method
     * @private
     */
    processRefs: function(){
        var refs = this.refs;
        if(refs){
            Ext.Object.each(refs, function(key, val){
                this[key] = this.query(val)[0];
            }, this);
        }
    }
});
</code></pre>
<p>To Integrate the override in your project just add it to a file called &#8220;Container&#8221; in your &#8220;app/overrides&#8221; folder and &#8220;required&#8221; it in your application.</p>]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2013/05/retrieving-references-to-internal-view-components/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Launching Sencha Insights</title>
		<link>http://www.swarmonline.com/2013/03/launching-sencha-insights/</link>
		<comments>http://www.swarmonline.com/2013/03/launching-sencha-insights/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 10:18:08 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Ext JS]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Sencha Touch]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1856</guid>
		<description><![CDATA[This week we announce the official launch of Sencha Insights, with the first issue arriving in subscribers&#8217; [...]]]></description>
				<content:encoded><![CDATA[This week we announce the official launch of <a title="Sencha Insights - a curated newsletter focusing on Sencha and related web technologies" href="http://www.senchainsights.com" target="_blank">Sencha Insights</a>, with the first issue arriving in subscribers&#8217; inboxes today. We&#8217;ve worked hard creating the website, promoting the launch and compiling the first issue and are excited to see it coming to a head, and looking forward to the future issues to come.</p>
<p>In the week running up to the first issue being released we have had close to 100 subscribers signing up and are delighted to see that number growing every day. We hope to continue this growth once the first issue is sent out and the word begins to spread.</p>
<h3>What is Sencha Insights?</h3>
<p>Sencha Insights is a curated newsletter focusing on Sencha and other related web technologies. We created Sencha Insights because we we felt that there was a lot of great content being produced and thought that it wasn&#8217;t always being seen by the community (ourselves included!). A place where this material was collected and distributed in an easy to consume way would be very beneficial to the community.</p>
<h3>How can I subscribe?</h3>
<p>You can subscribe to the newsletter by heading over to <a title="Sencha Insights" href="http://www.SenchaInsights.com" target="_blank">www.SenchaInsights.com</a> and entering your email address in the form. Once you&#8217;ve confirmed your email address you will receive the newsletter every second Wednesday.]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2013/03/launching-sencha-insights/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Documenting your Sencha apps with JSDuck</title>
		<link>http://www.swarmonline.com/2013/02/documenting-your-sencha-apps-with-jsduck/</link>
		<comments>http://www.swarmonline.com/2013/02/documenting-your-sencha-apps-with-jsduck/#comments</comments>
		<pubDate>Thu, 28 Feb 2013 02:52:12 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Ext JS]]></category>
		<category><![CDATA[Sencha Touch]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1724</guid>
		<description><![CDATA[JSDuck is an API Documentation generator created to make documenting Ext JS, Sencha Touch and any other [...]]]></description>
				<content:encoded><![CDATA[<strong>JSDuck is an API Documentation generator created to make documenting Ext JS, Sencha Touch and any other JavaScript applications a walk in the park. JSDuck was originally created by <a href="https://twitter.com/renku">Rene Saarsoo</a> but is now maintained by <a href="https://github.com/senchalabs">SenchaLabs</a> and is available on <a href="https://github.com/senchalabs/jsduck">GitHub</a>.</strong></p>
<p><span id="more-1724"></span></p>
<p>In a nutshell JSDuck parses your source code and generates documentation based on the comments within the code &#8211; with a similarly awesome interface as the <a href="http://docs.sencha.com/ext-js/4-2/">Ext JS</a> and <a href="http://docs.sencha.com/touch/2-1/">Sencha Touch</a> docs.</p>
<p>In this blog post we&#8217;re going to talk about how you can easily get JSDuck integrated into your project and easily generate some excellent documentation for you app*.</p>
<p><span style="font-size: 10px;">*Unfortunately, JSDuck won&#8217;t improve the content or relevancy of your documentation! <img src='http://www.swarmonline.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></p>
<h2>Installing JSDuck</h2>
<p>Installing JSDuck is very straightforward and involves very few steps.</p>
<h3>On Mac</h3>
<p>Mac users should be able to install the package using the gem. Open a Terminal window and type the following:</p>
<pre><code>[sudo] gem install jsduck
</code></pre>
<h3>On Windows</h3>
<p>Windows users can download an EXE package that contains all the dependencies needed from the SoureForge <a href="https://sourceforge.net/projects/jsduck/files/">downloads</a> page. Simply save this file somewhere convenient and accesible from your project and you&#8217;re good to go!</p>
<h2>Running JSDuck</h2>
<p>To get started we&#8217;re going to run JSDuck on the Ext JS SDK and generate the documentation for the entire Ext JS framework with the bare bones command. We start by opening a Terminal(or Command Prompt) window and navigate to the SDK folder on your hard drive. If you don&#8217;t have the SDK on your machine you can download it from the <a href="http://www.sencha.com/products">Sencha</a> website. From here we can type the following command to generate our documentation set:</p>
<p><strong>For Mac</strong></p>
<pre><code>jsduck src --output newdocs
</code></pre>
<p><strong>For Windows</strong></p>
<pre><code>path/to/jsduck.exe src --output newdocs
</code></pre>
<p>If you open the SDK in Finder/Explorer you should see the new &#8220;newdocs&#8221; folder, and if you open the index.html you should see a familiar set of Ext JS docs.</p>
<p>So what did we actually do here? The first part &#8211; &#8220;<strong>jsduck</strong>&#8221; &#8211; is the command to be executed. The second &#8211; &#8220;<strong>src</strong>&#8221; &#8211; is the folder we want JSDuck to analyse and parse. Lastly we specify the output folder by using the &#8220;<strong>&#8211;output</strong>&#8221; argument.</p>
<p>In this example we are pointing to the framework&#8217;s source code folder but for your own application you would point to your application&#8217;s &#8220;<strong>app</strong>&#8221; folder or, if you wanted to include the Ext JS docs in your documentation the folder above so your app folder and the Ext JS source are both parsed.</p>
<p>There are various other arguments that can be added to this basic command which we will introduce later in the series.</p>
<h2>Our Sample Application</h2>
<p>Now that we can generate our documentation we can start to add comments to our own application&#8217;s code which will then be picked up by JSDuck and included in our documentation. We will be using a simple application as the basis of our demonstration. The code for this application can be found on <a href="https://github.com/SwarmOnline/JSDuckDemo">GitHub</a>.</p>
<p>The application consists of the following classes and components and is extremely trivial and contrived:<br />
- a Person model<br />
- a People store<br />
- a People controller<br />
- a PeopleDataView</p>
<p>The app simply creates and shows the PeopleDataView which displays the contents of the People stor, displaying each person&#8217;s Name and Date Of Birth. It will also, optionally, colour the background the Person&#8217;s Favourite Colour. The functionality of the app is irrelevant &#8211; as long as we have a few methods, config options and events to document!</p>
<p>Whenever we say we are building the documentation we are using the following command (from our root project folder) &#8211; unless otherwise stated! This will generate our documentation into a &#8220;<strong>docs</strong>&#8221; folder within our project.</p>
<pre><code>jsduck JSDuckDemo --output docs
</code></pre>
<p>If you run this command now and take a look at the output you will see an empty documentation app.</p>
<h2>Commenting you Source Code</h2>
<p>Now we have a small app to document we will get stuck in!</p>
<h3>Classes</h3>
<p>We will start by adding comments to each of our classes so they are recognised by JSDuck. We are using the standard <code>Ext.define</code> class syntax so we don&#8217;t have to worry about explicitly telling JSDuck what our class is called, what it extends etc &#8211; JSDuck already knows!</p>
<p>As a demonstration we will add the following comment to the top of our <code>JSDuckDemo.model.Person</code> class and then regenerate the documentation.</p>
<pre><code>/**
 * Holds data about a Person.
 */
Ext.define('JSDuckDemo.model.Person', {
    ...
});
</code></pre>
<p>Once regenerated we will see the Person model class appear in the documentation &#8211; something similar to the screenshot below:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/01PersonTree.png"><img class="aligncenter size-medium wp-image-1726" alt="Person model in documentation class tree" src="http://www.swarmonline.com/wp-content/uploads/2013/02/01PersonTree-300x117.png" width="300" height="117" /></a></p>
<p>You will also notice that the Person model&#8217;s documentation page references the class&#8217; inheritance hierarchy and includes all of the config options, methods and events that these classes bring.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/02PersonHierarchy.png"><img class="aligncenter size-medium wp-image-1727" alt="Person model class' inheritance hierarchy" src="http://www.swarmonline.com/wp-content/uploads/2013/02/02PersonHierarchy-300x108.png" width="300" height="108" /></a></p>
<p>The content of our comment is displayed in the header of the class&#8217; documentation page.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/03PersonHeader.png"><img class="aligncenter size-medium wp-image-1728" alt="Person model's documentation header" src="http://www.swarmonline.com/wp-content/uploads/2013/02/03PersonHeader-300x101.png" width="300" height="101" /></a></p>
<p>We will add similar comments to each of the other classes and regenerate our documentation so we have the following structure in our docs:</p>
<h3><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/04ClassTree.png"><img class="aligncenter size-medium wp-image-1729" alt="JSDuckDemo app's classes in documentation tree" src="http://www.swarmonline.com/wp-content/uploads/2013/02/04ClassTree-300x293.png" width="300" height="293" /></a></h3>
<h3>Config Options</h3>
<p>As you will have seen from the main framework&#8217;s documentation each class has various &#8216;config&#8217; options that allow users to customise the components. We will first look at how to annotate the config options in our application.</p>
<p>Our app has one config option &#8211; the <code>useFavouriteColour</code> config found in the <code>JSDuckDemo.view.PeopleDataView</code> component. This config accepts a boolean value and decides whether or not the background of each Person row will be coloured.</p>
<p>We can annotate this with the following comment:</p>
<pre><code>/**
 * @cfg {Boolean} useFavouriteColour This option determines whether the Person's details
 * will use their FavouriteColour as the background.
 */
 useFavouriteColour: true
</code></pre>
<p>So let&#8217;s look at each part:</p>
<p><strong>@cfg</strong> &#8211; This part tells JSDuck that the following property is a Config option and so will be filed under the &#8220;Config&#8221; section.</p>
<p><strong>{Boolean}</strong> &#8211; We put the config option&#8217;s type within curly braces after the @cfg. This could be a simple type such as String, Date, Boolean, Number or an Ext or application class such as <code>Ext.data.Store</code> or <code>JSDuckDemo.store.People</code>.</p>
<p><strong>useFavouriteColour</strong> &#8211; This is the name of the config option and should match the property&#8217;s name in the code.</p>
<p><strong>&lt;text&gt;</strong> &#8211; After the config&#8217;s name we can describe what the option does and how to use it.</p>
<p>With this comment in place if we regenerate our docs we will see a new item in the &#8220;config&#8221; dropdown and an entry that contains all the details we added:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/05PeopleDataViewMen-masked.png"><img class="aligncenter size-large wp-image-1735" alt="useFavouriteColour configuration in Config dropdown menu" src="http://www.swarmonline.com/wp-content/uploads/2013/02/05PeopleDataViewMen-masked-1024x316.png" width="640" height="197" /></a><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/06PeopleDataViewEntry.png"><img class="aligncenter size-large wp-image-1731" alt="useFavouriteColour configuration entry" src="http://www.swarmonline.com/wp-content/uploads/2013/02/06PeopleDataViewEntry-1024x110.png" width="640" height="68" /></a></p>
<p>For the observant among you, you will notice that we automatically get documentation entries for a &#8220;<strong>getUseFavouriteColour</strong>&#8221; and &#8220;<strong>setUseFavouriteColour</strong>&#8221; method. This is because the useFavouriteColour property is nested in the &#8220;<strong>config</strong>&#8221; property.</p>
<h3>Methods</h3>
<p>We document methods in a very similar way, by annotating the code with structured comments which will later be parsed.</p>
<p>We have added a custom method to the Person model class called &#8220;<strong>getAge</strong>&#8221; which returns the Person&#8217;s age, in years. It includes a parameter that will optionally return their age with decimal precision. We will document this by adding the following comment:</p>
<pre><code>/**
 * Returns the Person's age in years.
 * @param {Boolean} noRounding If true this will return the value as a decimal with no rounding. If false the value with be rounded to the nearest year.
 * @return {Number} The Person's age
 */
getAge: function(noRounding){
    ...
}
</code></pre>
<p>The first sentence provides the docs with the description of the method and what it does.</p>
<p>Secondly we use the &#8220;<strong>@param</strong>&#8221; flag to describe the parameters that the method accepts. In a similar manner to the Config option we define the type the parameter expects, within curly brackets. We then add the parameter&#8217;s name which should match the name in the code. Finally we describe the parameter and what the value means and does.</p>
<p>We can include as many @param items as we like and, if the parameter expects multiple types these can be included by separating them with a slash, e.g. {Boolean/String}.</p>
<p>In our example we really want the &#8220;<strong>noRounding</strong>&#8221; parameter to be optional so it defaults to false to give a round number. We can do this by changing the way we write the parameter&#8217;s name. If we wrap it in square brackets and provide a default value, this will document the parameter as optional. For example, we might change it to:</p>
<pre><code>* @param {Boolean} [noRounding=false] If true this will return the value as a decimal with no rounding. If false the value with be rounded to the nearest year.
</code></pre>
<p>The next flag we use is the &#8220;<strong>@return</strong>&#8221; which describes the data type that the method returns to us. If no value is returned we can use the &#8220;<strong>{void}</strong>&#8221; type.</p>
<p>When we regnerate the docs we see our method included with our comments and parameters.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/07GetAgeEntry.png"><img class="aligncenter size-large wp-image-1732" alt="getAge method's documentation entry" src="http://www.swarmonline.com/wp-content/uploads/2013/02/07GetAgeEntry-1024x279.png" width="640" height="174" /></a></p>
<p>If your method is private we can add the &#8220;<strong>@private</strong>&#8221; flag to it which will mark it as private and only display it in the docs when the user has checked the &#8220;private&#8221; box.</p>
<h3>Events</h3>
<p>Events are another major thing that must be documented. In our PeopleDataView component we have added a custom event called &#8216;personclick&#8217; that will fire when a PersonDataView row is clicked. The event will pass the DataView and the Person record to any handler functions.</p>
<p>We document events by adding familiar looking comment to the class. This comment is usually added above the event&#8217;s inclusion in the call to the &#8220;<strong>addEvents</strong>&#8221; method but can be included anywhere in your class.</p>
<pre><code>/**
 * @event personclick Fires when a Person row is clicked
 * @param {JSDuckDemo.view.PeopleDataView} view The PeopleDataView that raised the event
 * @param {JSDuckDemo.model.Person} record The Person record that was clicked
 */
'personclick'
</code></pre>
<p>The &#8220;<strong>@event</strong>&#8221; flag marks this comment as describing an event. We follow the flag by the event&#8217;s name and a description of the event and when it is fired.</p>
<p>We describe each of the event&#8217;s parameters in an identical way as we did with the methods. Notice the way we reference the custom types.</p>
<p>When we regenerate our docs we will see a new item in the events dropdown and an entry containing our documentation.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/08PersonClickMen-masked.png"><img class="aligncenter size-large wp-image-1736" alt="PersonClick event in Events dropdown menu" src="http://www.swarmonline.com/wp-content/uploads/2013/02/08PersonClickMen-masked-1024x462.png" width="640" height="288" /></a><br />
<a href="http://www.swarmonline.com/wp-content/uploads/2013/02/09PersonClickEntry.png"><img class="aligncenter size-large wp-image-1734" alt="PersonClick event documentation entry" src="http://www.swarmonline.com/wp-content/uploads/2013/02/09PersonClickEntry-1024x303.png" width="640" height="189" /></a></p>
<p>Notice how our parameters&#8217; types are automatically linked to the relavant class&#8217; documentation making it extremely easy for people to follow what types are expected.</p>
<h3>Properties</h3>
<p>Properties are the final item we&#8217;re going to discuss. We will add a property to our PeopleDataView class to keep track of whether the <code>useFavouriteColour</code> has been manually updated. In our <code>updateUseFavouriteColour</code> method we assign a boolean value to the property <code>useFavouriteColourUpdated</code>. To document this we add the following comments above this statement.</p>
<pre><code>/**
 * @property {Boolean} useFavouriteColourUpdated True if the useFavouriteColour configuration has been updated since init
 */
this.useFavouriteColourUpdated = true;
</code></pre>
<p>When we regenerate this we can see the property in our documentation.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/10updatedUseFavouriteColourEntry.png"><img class="aligncenter size-large wp-image-1743" alt="updatedUseFavouriteColour property documentation entry" src="http://www.swarmonline.com/wp-content/uploads/2013/02/10updatedUseFavouriteColourEntry-1024x77.png" width="640" height="48" /></a></p>
<h2>Conclusion</h2>
<p>We&#8217;ve covered quite a few things in this post, namely how to:</p>
<ul>
<li>install JSDuck</li>
<li>generate documentation using JSDuck</li>
<li>Annotate your configs, methods, events and properties with JSDuck-parseable comments</li>
</ul>
<p>Armed with this knowledge there is now no excuse for your project not to have good, navigable and up to date documentation! With the command line tools it is ridiculously easy to include documentation building in your build process so your project&#8217;s docs are never out of date.</p>
<p>There are a lot more features of JSDuck that we haven&#8217;t gone into here so we will continue looking into JSDuck in future blog posts.]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2013/02/documenting-your-sencha-apps-with-jsduck/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Localising Sencha Touch and Ext JS applications with Ux.locale.Manager</title>
		<link>http://www.swarmonline.com/2013/02/localising-sencha-touch-and-ext-js-applications-with-ux-locale-manager/</link>
		<comments>http://www.swarmonline.com/2013/02/localising-sencha-touch-and-ext-js-applications-with-ux-locale-manager/#comments</comments>
		<pubDate>Tue, 19 Feb 2013 05:00:10 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1589</guid>
		<description><![CDATA[Using the Ux.locale.Manager extension This blog post is going to discuss how to use the excellent Ux.locale.Manager [...]]]></description>
				<content:encoded><![CDATA[<h1>Using the Ux.locale.Manager extension</h1>
<p>This blog post is going to discuss how to use the excellent <a href="https://github.com/mitchellsimoens/Ux.locale.Manager">Ux.locale.Manager</a> extension (created by Sencha&#8217;s <a href="https://twitter.com/SenchaMitch">Mitchell Simoens</a>) which allows us to easily integrate localisation into our Sencha Touch and Ext JS applications.</p>
<p>We will focus primarily on Sencha Touch in this tutorial but the principles and techniques can equally be applied to Ext JS 4 projects without too many tweaks.</p>
<p>By the end of the article we should have achieved the following:</p>
<ul>
<li>Integrated the extension with a blank Sencha Touch project.</li>
<li>Explained the configuration options available.</li>
<li>Demonstrated its use with an example</li>
<li>Created our own overrides to customise it further</li>
<li>Dealt with more complex situations such as DataViews</li>
</ul>
<p><span id="more-1589"></span></p>
<p>And if you&#8217;re still awake by the end then please leave a comment if you have any questions, comments or, heaven forbid, corrections! <img src='http://www.swarmonline.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Extension Purpose &amp; Anatomy</h2>
<p>As I&#8217;m sure you are aware the purpose of this extension is to allow an entire application to be localised to any language. It does this by loading in external locale files containing all string literals that need to be used. The components that use these strings are then located and updated to the loaded value.</p>
<p>The extension is made up of a Manager class, which is responsible for coordinating the updates and loading of the locale files, and the component overrides. These overrides define a <strong><em>setLocale</em></strong> method which processes the keys provided and updates the component&#8217;s markup with the translated value. The base Ext.Component also has an override to its constructor so this translation and replacement occurs when new components are created.</p>
<h2>Creating a Blank Project</h2>
<p>We&#8217;ll start by creating a blank Sencha Touch project structure using <a href="http://www.sencha.com/products/sencha-cmd/download">Sencha Cmd</a> which does all the heavy lifting for us. If you prefer to create your projects manually or if you have an existing project you want to work with then that&#8217;s fine &#8211; just be sure you have the auto-loading mechanism working as we will make use of it throughout.</p>
<p>We will create our new project using the following command from inside a Sencha Touch 2.1 SDK directory.</p>
[javascript]
sencha generate app LocaleManagerTutorial LocaleManagerTutorial<br />
[/javascript]
<p>Once this is complete you should have a project structure similar to the one in the screenshot below.</p>
<p style="text-align: center;"><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/0-ProjectStructure.png"><img class="aligncenter  wp-image-1614" title="ProjectStructure" alt="" src="http://www.swarmonline.com/wp-content/uploads/2013/02/0-ProjectStructure.png" width="410" height="452" /></a></p>
<p>If you&#8217;re in a rush then you can <a>download the blank project structure</a> and save a bit of time!</p>
<h2>Integrating the Extension</h2>
<p>Now we have our plain vanilla project we can now start integrating the extension. We&#8217;ll start by getting all the right files into our project, then move on to how we integrate it with our code so the extension is loaded.</p>
<h3>Importing the extension</h3>
<p>We&#8217;ll first need to grab the source from its <a href="https://github.com/mitchellsimoens/Ux.locale.Manager">GitHub repository</a> by <a href="https://github.com/mitchellsimoens/Ux.locale.Manager/archive/master.zip">downloading its source as a zip</a> or by cloning the entire repository.</p>
<p>Once we have a local copy of the extension&#8217;s source we can paste the &#8220;<strong>Ux</strong>&#8221; folder into the &#8220;<strong>touch/src/ux</strong>&#8220; folder within our project. We place it here so the <strong><em>Ext.Loader</em></strong> class can easily locate it and pull in all the classes we need when loading and building our application.</p>
<p>Our new project structure should resemble the following screenshot:</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/0-ProjectStructure-inc-Extension1.png"><img class="aligncenter size-medium wp-image-1619" title="Project Structure inc Extension" alt="" src="http://www.swarmonline.com/wp-content/uploads/2013/02/0-ProjectStructure-inc-Extension1-151x300.png" width="151" height="300" /></a></p>
<h3>Autoloading the extension</h3>
<p>Our next step is to reference the extension in our code so it is loaded and available to us.</p>
<p>We start by setting up an <strong><em>Ext.Loader</em></strong> path at the start of our <strong>app.js</strong> file. We update the existing <strong><em>Ext.Loader.setPath</em></strong> call&#8217;s object parameter with an additional key/value pair.</p>
[javascript]
    Ext.Loader.setPath({<br />
        &#8216;Ext&#8217;: &#8216;touch/src&#8217;,<br />
        &#8216;LocaleManagerTutorial&#8217;: &#8216;app&#8217;,<br />
        &#8216;Ux&#8217;: &#8216;touch/src/ux/Ux&#8217;<br />
    });<br />
[/javascript]
<p>This code instructs Sencha Touch to look for any classes we reference with a root namespace of &#8220;<strong>Ux</strong>&#8220; to be loaded from the folder we copied in during the previous step.</p>
<p>Next we add all of the Sencha Touch locale overrides, and the Manager itself, to the <strong><em>requires</em></strong> array in the <strong><em>Ext.application</em></strong> setup. This will ensure they are loaded when the application starts and so our components can take advantage of their functionality.</p>
<p>The <strong><em>Ext.application</em></strong> call in <strong>app.js</strong> should now look like the following:</p>
[javascript]
    Ext.Loader.setPath({<br />
        &#8216;Ext&#8217;: &#8216;touch/src&#8217;,<br />
        &#8216;LocaleManagerTutorial&#8217;: &#8216;app&#8217;,<br />
        &#8216;Ux&#8217;: &#8216;touch/src/ux/Ux&#8217;<br />
    });</p>
<p>    Ext.application({<br />
        name: &#8216;LocaleManagerTutorial&#8217;,</p>
<p>        requires: [<br />
            'Ext.MessageBox',</p>
<p>            'Ux.locale.Manager',<br />
            'Ux.locale.override.st.Component',<br />
            'Ux.locale.override.st.Button',<br />
            'Ux.locale.override.st.Container',<br />
            'Ux.locale.override.st.TitleBar',<br />
            'Ux.locale.override.st.field.Field',<br />
            'Ux.locale.override.st.field.DatePicker',<br />
            'Ux.locale.override.st.form.FieldSet',<br />
            'Ux.locale.override.st.picker.Picker',<br />
            'Ux.locale.override.st.picker.Date'</p>
<p>        ]
<p>        // ommitted for brevity<br />
    });<br />
[/javascript]
<p>If you now load your sample application you should be able to open the Developer Tools and type &#8220;<strong>Ux.locale.Manager</strong>&#8220;, hit enter and see it returns an object. This means it&#8217;s all loaded and we&#8217;re ready to go!</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Extension-Loaded-Confirmation.png"><img class="aligncenter size-medium wp-image-1609" title="Extension Loaded Confirmation" alt="" src="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Extension-Loaded-Confirmation-300x69.png" width="300" height="69" /></a></p>
<h2>Initialising and Configuring</h2>
<p>After taking a moment to bask in our success of getting the extension integrated with our project we can move onto the real work &#8211; initialising and configuring it!</p>
<p>Before we start we&#8217;re going to go ahead and remove everything from the <strong><em>launch</em></strong> function within our <strong>app.js</strong> <em>except the line that destroys the loading indicator</em>. We are going to work from a clean slate so we&#8217;ll throw away the example code for now:</p>
[javascript]
    &#8230;<br />
    launch: function() {<br />
        // Destroy the #appLoadingIndicator element<br />
        Ext.fly(&#8216;appLoadingIndicator&#8217;).destroy();<br />
    }<br />
    &#8230;<br />
[/javascript]
<p>Before we initialise the extension we must call its <strong><em>setConfig</em></strong> method to configure it with any options we want. For the majority of cases we won&#8217;t need to change the default values but it&#8217;s good to include it so we can make changes when we need to. To do this we add the following snippet to the start of the <strong><em>launch</em></strong> method:</p>
[javascript]
Ux.locale.Manager.setConfig({<br />
    ajaxConfig : {<br />
        method : &#8216;GET&#8217;<br />
    },<br />
    language : &#8216;en&#8217;,<br />
    tpl : &#8216;locales/{locale}.json&#8217;,<br />
    type : &#8216;ajax&#8217;<br />
});<br />
[/javascript]
<p>So let&#8217;s go through what each of these actually do:</p>
<ul>
<li><strong>ajaxConfig</strong> &#8211; this object allows us to configure the AJAX request that is sent to retrieve the locale&#8217;s data. This can take any of the standard <strong><em>Ext.Ajax.request</em></strong> options. <em>It is important to note that if you include a url or callback option in this object it will be overridden by the extension.</em></li>
<li><strong>language</strong> &#8211; this defines the default language to load when the extension is initialised. This value will be combined with the <strong>tpl</strong> value to produce the URL the locale is loaded from.</li>
<li><strong>tpl</strong> &#8211; we can customise the location that our locales are loaded from by editing this value. The locale (initially based on the <strong>language</strong> config) is injected into the string before loading. You could change this, for example, to load from a PHP page by providing the following tpl value: <strong><em>&#8216;../locales/getLocaleData.php?language={locale}&#8217;</em></strong></li>
<li><strong>type</strong> &#8211; this will be used to switch the method that the locale data is loaded by. At the moment only AJAX is supported but loading via a script tag is in the future plans.</li>
</ul>
<p>Once we have set any configuration options we want we can call the Manager&#8217;s <strong><em>init</em></strong> method and the extension will get to work and load our locale file and customise each component that is configured to be. We call this just after the <strong><em>setConfig</em></strong> call so our <strong><em>launch</em></strong> method looks like this:</p>
[javascript]
Ux.locale.Manager.setConfig({<br />
    ajaxConfig : {<br />
        method : &#8216;GET&#8217;<br />
    },<br />
    language : &#8216;en&#8217;,<br />
    tpl : &#8216;locales/{locale}.json&#8217;,<br />
    type : &#8216;ajax&#8217;<br />
});</p>
<p>Ux.locale.Manager.init();<br />
[/javascript]
<p>If you run your application now you will see a nasty console error telling us that there is no such file as en.json! We will follow the default structure and create a <strong><em>locales</em></strong> folder in the main project folder. We will then create a JSON file named <strong><em>en.json</em></strong> and populate it with an empty object.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Locale-File-Location.png"><img class="aligncenter size-medium wp-image-1610" title="Locale File Location" alt="" src="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Locale-File-Location-300x217.png" width="300" height="217" /></a></p>
[javascript]
{<br />
&#8230;<br />
}<br />
[/javascript]
<p>Running your application now should result in a nice empty screen and no console errors. If you take a look in your Network tab and filter by &#8220;XHR&#8221; you will see our <strong><em>en.json</em></strong> file being loaded.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Locale-Network-Load.png"><img class="aligncenter size-medium wp-image-1612" title="Locale Network Load" alt="" src="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Locale-Network-Load-300x82.png" width="300" height="82" /></a></p>
<p>Before we go any further we&#8217;ll create a second locale file and demonstrate how to switch between locales. Create a second JSON file in the <strong><em>locales</em></strong> folder called <strong><em>fr.json</em></strong> and populate it with an empty object.</p>
<p>If we reload our application, open the console and type the following then hit enter:</p>
[javascript]
Ux.locale.Manager.updateLocale(&#8216;fr&#8217;);<br />
[/javascript]
<p>We should see a flash of load mask and if you look in the Network tab once more you should see the <strong><em>fr.json</em></strong>file being loaded in &#8211; perfect!</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Locale-Network-Load-2.png"><img class="aligncenter size-medium wp-image-1611" title="Locale Network Load 2" alt="" src="http://www.swarmonline.com/wp-content/uploads/2013/02/0-Locale-Network-Load-2-300x96.png" width="300" height="96" /></a></p>
<p>We&#8217;ll demonstrate what this is actually means in the next section so keep reading!</p>
<h2>Simple Usage</h2>
<p>By now you&#8217;ll be itching to get something localised so your app has instant international appeal, so let&#8217;s get to it!</p>
<p>We&#8217;re going to start by creating a simple <strong><em>Ext.field.Text</em></strong> (purely because it has multiple things we can localise!); localise its <strong><em>label</em></strong> and <strong><em>placeHolder</em></strong> values and then add it to a Container in the Viewport. We&#8217;ll start by defining our localised strings in our <strong><em>en.json</em></strong> and <strong><em>fr.json</em></strong> files. Update the files with the following:</p>
<p><strong>en.json<br />
</strong></p>
[javascript]
{<br />
    &quot;Field1&quot;: {<br />
        &quot;label&quot; : &quot;ENGLISH label&quot;,<br />
        &quot;placeHolder&quot; : &quot;ENGLISH placeHolder&quot;<br />
    }<br />
}<br />
[/javascript]
<p><strong>fr.json<br />
</strong></p>
[javascript]
{<br />
    &quot;Field1&quot;: {<br />
        &quot;label&quot; : &quot;label Français&quot;,<br />
        &quot;placeHolder&quot; : &quot;espace réservé Française&quot;<br />
    }<br />
}<br />
[/javascript]
<p>We can now create the textfield that these translations will become part of. We will simply create a new Ext.field.Text in the launch method within app.js.</p>
[javascript]
var field = Ext.create(&#8216;Ext.field.Text&#8217;, {<br />
    label: &#8216;ENGLISH Label&#8217;,<br />
    placeHolder: &#8216;English placeHolder&#8217;<br />
});</p>
<p>// wrap in container so it doesn&#8217;t get stretched<br />
Ext.Viewport.add({<br />
    xtype: &#8216;container&#8217;,<br />
    items: [field]
});<br />
[/javascript]
<p>If we reload our app we can see the field with its label and placeHolder displayed in English with no way to change it to French (or German, or Spanish etc etc).</p>
<p>Finally we&#8217;ve got to the bit where the magic happens that we&#8217;ve been building to since the start of the article… We update the field&#8217;s configuration to remove the hard-coded English values and instead use a <strong><em>locales</em></strong> config option to define the &#8220;dot-notation&#8221; path to the required string in our JSON language files for each property. You can see this in the code below:</p>
[javascript]
var field = Ext.create(&#8216;Ext.field.Text&#8217;, {<br />
    locales: {<br />
        label: &#8216;Field1.label&#8217;,<br />
        placeHolder: &#8216;Field1.placeHolder&#8217;<br />
    }<br />
});<br />
[/javascript]
<p>If we now reload our application &#8211; what do we see? Exactly the same thing? Hopefully! The field looks the same but its <strong><em>label</em></strong> and <strong><em>placeHolder</em></strong> values are coming from our locale file rather than the hard-coded values we had before.</p>
<p>You&#8217;ll remember in the last section we updated the locale to French using the following code:</p>
[javascript]
Ux.locale.Manager.updateLocale(&#8216;fr&#8217;);<br />
[/javascript]
<p>If we do the same now we will see the benefits of using this extension immediately. The app is now in French! C&#8217;est très bien!</p>
<h3>An Explanation</h3>
<p>So what did we just do here?</p>
<p>Our JSON locale files can contain any depth of nested objects that are referenced using the standard dot-notation within the extension. These items should be used to populate any string literal within your application.</p>
<p>We applied them to our TextField component by using the <strong><em>locales</em></strong> configuration option. When a new locale is loaded the extension locates all of the existing components that have this option set (using ComponentQuery) and, if it exists in one of the included overrides, calls the <strong><em>setLocale</em></strong> method of that component. Within this method each of the defined options are looked up against the current locale file (using the dot-notation string we provided) and then updates it using the property&#8217;s setter method.</p>
<h2>Filling in the blanks</h2>
<p>Occasionally you might find that the extension&#8217;s overrides aren&#8217;t sufficient for the components you are using and you need to create your own. This is very easy and, by following the pattern the existing ones do, we can create our own.</p>
<p><strong>A Scenario</strong></p>
<p>Imagine you have a Select Field with a series of options (we&#8217;ll use colours as an example) and we want these to be translated in the same way the field&#8217;s label is. Unfortunately that functionality isn&#8217;t covered by the built in overrides so we&#8217;ll describe how we can achieve this by creating our own.</p>
<p>We begin by creating a simple SelectField with our colour options and adding it to our Viewport container.</p>
[javascript]
var selectField = Ext.create(&#8216;Ext.field.Select&#8217;, {<br />
    locales: {<br />
        label: &#8216;SelectField1.label&#8217;<br />
    },<br />
    valueField: &#8216;value&#8217;,<br />
    displayField: &#8216;name&#8217;,<br />
    options: [{<br />
        name: 'Blue',<br />
        value: 'Blue'<br />
    }, {<br />
        name: 'Red',<br />
        value: 'Red'<br />
    }, {<br />
        name: 'Green',<br />
        value: 'Green'<br />
    }]
});</p>
<p>Ext.Viewport.add({<br />
    xtype: &#8216;container&#8217;,<br />
    items: [field, selectField]
});<br />
[/javascript]
<p>The <strong><em>Ext.field.Select</em></strong> component extends from the base <strong><em>Ext.field.Field</em></strong> class and so inherits the label localisation defined there but it doesn&#8217;t have any localisation of its own. We will create a new override in the extension&#8217;s folder.</p>
<p><a href="http://www.swarmonline.com/wp-content/uploads/2013/02/0-SelectField-Override-File-Location.png"><img class="aligncenter size-medium wp-image-1615" title="SelectField Override File Location" alt="" src="http://www.swarmonline.com/wp-content/uploads/2013/02/0-SelectField-Override-File-Location-219x300.png" width="219" height="300" /></a></p>
<p>We then create a basic override for the Select field and include a simple <strong><em>setLocale</em></strong> method copied from another override to get us started. We have added an <strong><em>options</em></strong> variable which picks up the <strong><em>options</em></strong> config of the <strong><em>locales</em></strong> object. We will use this to localise the field&#8217;s options.</p>
[javascript]
Ext.define(&#8216;Ux.locale.override.st.field.Select&#8217;, {<br />
    override : &#8216;Ext.field.Select&#8217;,</p>
<p>    requires : [<br />
        'Ux.locale.override.st.field.Field'<br />
    ],</p>
<p>    setLocale : function(locale) {<br />
        var me = this,<br />
            locales = me.locales || me.getInitialConfig().locales,<br />
            options = locales.options,<br />
            manager = me.locale;</p>
<p>        me.callParent(arguments);<br />
    }<br />
});<br />
[/javascript]
<p>Now we must perform the actual localisation of the Select field&#8217;s options. We do this by first checking that the options have been specified for localisation (we might not want to localise them in every select field). Once we&#8217;re happy it has been defined we can lookup the options&#8217; value using the Ux.locale.Manager&#8217;s <strong><em>get</em></strong> method and then pass the result of this into the Select field&#8217;s <strong><em>setOptions</em></strong> method.</p>
[javascript]
Ext.define(&#8216;Ux.locale.override.st.field.Select&#8217;, {<br />
    override : &#8216;Ext.field.Select&#8217;,</p>
<p>    requires : [<br />
        'Ux.locale.override.st.field.Field'<br />
    ],</p>
<p>    setLocale : function(locale) {<br />
        var me = this,<br />
            locales = me.locales || me.getInitialConfig().locales,<br />
            options = locales.options,<br />
            manager = me.locale;</p>
<p>        if(options){<br />
            options = manager.get(options, []);</p>
<p>            this.setOptions(options);<br />
        }</p>
<p>        me.callParent(arguments);<br />
    }<br />
});<br />
[/javascript]
<p>We must now go back to our app.js file and add a reference to this new override to the <strong><em>require</em></strong> config option.</p>
[javascript]
    &#8230;<br />
    requires: [<br />
        'Ext.MessageBox',</p>
<p>        'Ux.locale.Manager',<br />
        'Ux.locale.override.st.Component',<br />
        'Ux.locale.override.st.Button',<br />
        'Ux.locale.override.st.Container',<br />
        'Ux.locale.override.st.TitleBar',<br />
        'Ux.locale.override.st.field.Field',<br />
        'Ux.locale.override.st.field.DatePicker',<br />
        'Ux.locale.override.st.form.FieldSet',<br />
        'Ux.locale.override.st.picker.Picker',<br />
        'Ux.locale.override.st.picker.Date',<br />
        'Ux.locale.override.st.field.Select'<br />
    ]
    &#8230;<br />
[/javascript]
<p>Finally we add our options to our English and French locale files and update our SelectField&#8217;s configuration to include an <strong><em>options</em></strong> config in the <strong><em>locales</em></strong> object.</p>
<p><strong>app.js</strong></p>
[javascript]
var selectField = Ext.create(&#8216;Ext.field.Select&#8217;, {<br />
    locales: {<br />
        label: &#8216;SelectField1.label&#8217;,<br />
        options: &#8216;SelectField1.options&#8217;<br />
    },<br />
    valueField: &#8216;value&#8217;,<br />
    displayField: &#8216;name&#8217;<br />
});<br />
[/javascript]
<p><strong>en.json</strong></p>
[javascript]
{<br />
    &quot;Field1&quot;: {<br />
        &quot;label&quot; : &quot;ENGLISH label&quot;,<br />
        &quot;placeHolder&quot; : &quot;ENGLISH placeHolder&quot;<br />
    },</p>
<p>    &quot;SelectField1&quot;: {<br />
        &quot;label&quot; : &quot;Colour:&quot;,<br />
        &quot;options&quot;: [{<br />
            &quot;name&quot;: &quot;Blue&quot;,<br />
            &quot;value&quot;: &quot;Blue&quot;<br />
        }, {<br />
            &quot;name&quot;: &quot;Red&quot;,<br />
            &quot;value&quot;: &quot;Red&quot;<br />
        }, {<br />
            &quot;name&quot;: &quot;Green&quot;,<br />
            &quot;value&quot;: &quot;Green&quot;<br />
        }]
    }<br />
}<br />
[/javascript]
<p><strong>fr.json</strong></p>
[javascript]
{<br />
    &quot;Field1&quot;: {<br />
        &quot;label&quot; : &quot;label Français&quot;,<br />
        &quot;placeHolder&quot; : &quot;espace réservé Française&quot;<br />
    },</p>
<p>    &quot;SelectField1&quot;: {<br />
        &quot;label&quot; : &quot;Coleur:&quot;,<br />
        &quot;options&quot;: [{<br />
            &quot;name&quot;: &quot;Bleu&quot;,<br />
            &quot;value&quot;: &quot;Bleu&quot;<br />
        }, {<br />
            &quot;name&quot;: &quot;Rouge&quot;,<br />
            &quot;value&quot;: &quot;Rouge&quot;<br />
        }, {<br />
            &quot;name&quot;: &quot;Vert&quot;,<br />
            &quot;value&quot;: &quot;Vert&quot;<br />
        }]
    }<br />
}<br />
[/javascript]
<p>You can now reload your app and call the updateLocale method to switch languages and see the options change.</p>
<h2>Dealing with DataViews</h2>
<p>DataViews (and Lists of course) are a slightly trickier customer with regards to localisation using this approach because they don&#8217;t quite follow the same rules. The most common scenario is that the DataView&#8217;s template includes string literals in the form of labels which, unfortunately, don&#8217;t have a built in setter for as they are embedded in the view&#8217;s generated HTML. This section is going to explain one approach for overcoming this problem.</p>
<p>First we&#8217;ll create a quick DataView to demonstrate our problem and to use with our solution. In this example we must create a class extending the Ext.DataView component so we can add custom methods to it. We create a new file in the <strong><em>view</em></strong> folder called <strong><em>MyDataView.js</em></strong> and add it to the <strong><em>require</em></strong> option in our app.js. We can then instantiate it in the <strong><em>launch</em></strong> method, adding to the Viewport&#8217;s child container</p>
<p><strong>view/MyDataView.js</strong></p>
[javascript]
Ext.define(&#8216;LocaleManagerTutorial.view.MyDataView&#8217;, {</p>
<p>    extend: &#8216;Ext.DataView&#8217;,</p>
<p>    alias: &#8216;widget.mydataview&#8217;,</p>
<p>    config: {<br />
        height: 500,<br />
        itemTpl: &#8216;Name: {name}&#8217;,<br />
        store: Ext.create(&#8216;Ext.data.Store&#8217;, {<br />
            fields: ['name'],<br />
            data: [{name: 'Stuart'}, {name: 'Andrew'}]
        })<br />
    }<br />
});<br />
[/javascript]
<p><strong>app.js</strong></p>
[javascript]
&#8230;<br />
    requires: [<br />
        ...<br />
        'LocaleManagerTutorial.view.MyDataView'<br />
        ...<br />
    ]
&#8230;<br />
[/javascript]
<p><strong>app.js launch method</strong></p>
[javascript]
Ext.Viewport.add({<br />
    xtype: &#8216;mydataview&#8217;<br />
});<br />
[/javascript]
<p>We should now have a dataview in our Viewport but unfortunately the &#8220;Name&#8221; labels are hardcoded to their English translation. So how do we fix this?</p>
<p>We start by adding a method to the MyDataView class called <strong><em>getStringLiterals</em></strong> &#8211; we will use this to look up and return all string literals used in the template. In our case we only have one but you could return many key/value pairs in the returned object.</p>
[javascript]
&#8230;<br />
getStringLiterals: function(){<br />
    return {<br />
        nameLabel: Ux.locale.Manager.get(&#8216;MyDataView.nameLabel&#8217;)<br />
    };<br />
}<br />
&#8230;<br />
[/javascript]
<p>Next we must override the <strong><em>prepareData</em></strong> method which is used to process each records before sending it to be rendered. We can hijack this method and use it to merge the string literals (returned from the getStringLiterals method) with the data object being sent to the template.</p>
[javascript]
&#8230;<br />
prepareData: function(data){<br />
    data = this.callParent(arguments);</p>
<p>    return Ext.apply(data, this.getStringLiterals());<br />
}<br />
&#8230;<br />
[/javascript]
<p>We start by calling the original prepareData method so we don&#8217;t alter its functionality and then we merge the translated data with the data object. Now we have a <strong><em>nameLabel</em></strong> property in our data being passed to the template so we can replace the hardcoded &#8220;Name:&#8221; value with a placeholder for the &#8220;nameLabel&#8221;<br />
property.</p>
[javascript]
    &#8230;<br />
    itemTpl: &#8216;{nameLabel}: {name}&#8217;<br />
    &#8230;<br />
[/javascript]
<p>Finally we must add the translations to our en.json and fr.json files otherwise the DataView won&#8217;t display a label.</p>
<p>Our labels are now coming from our locale file but you&#8217;ll notice that it doesn&#8217;t get updated when we call the <strong><em>updateLocale</em></strong> method. We now need to fill in the blank and create an override for the DataView class to perform a refresh of the view when the locale is changed.</p>
<p>We do this in the same way as before by creating a <strong><em>DataView.js</em></strong> file in the &#8220;<strong>src/ux/Ux/locale/override/st</strong>&#8220; with the following code to perform the refresh.</p>
<p><strong>Ux/locale/override/st/DataView.js</strong></p>
[javascript]
Ext.define(&#8216;Ux.locale.override.st.DataView&#8217;, {<br />
    override : &#8216;Ext.DataView&#8217;,</p>
<p>    requires : [<br />
        'Ux.locale.override.st.Component'<br />
    ],</p>
<p>    setLocale : function(locale) {<br />
        var me = this,<br />
            locales = me.locales || me.getInitialConfig().locales,<br />
            manager = me.locale;</p>
<p>        me.callParent(arguments);</p>
<p>        me.refresh();<br />
    }<br />
});<br />
[/javascript]
<p>We must also add this class to the require config in the app.js file.</p>
<p><strong>app.js</strong></p>
[javascript]
    &#8230;<br />
    requires: [<br />
        ...<br />
        'Ux.locale.override.st.DataView'<br />
        ...<br />
    ]
    &#8230;<br />
[/javascript]
<p>Lastly, we must tell the Locale Manager that we want the MyDataView to be localised so we must add the <strong><em>enableLocale</em></strong> and a blank <strong><em>locales</em></strong> (a quirk of the extension) to the config.</p>
[javascript]
    &#8230;<br />
    config: {<br />
        enableLocale: true,<br />
        locales: {},<br />
        &#8230;<br />
    }<br />
    &#8230;<br />
[/javascript]
<p>Once we have done that we can refresh our app and switch the locales and see the dataview refresh itself with the new localised labels being merged into the template.</p>
<h2>Phew! We made it!</h2>
<p>Hopefully you have seen just how easy it is to integrate localisation with your Sencha Touch and Ext JS applications with this excellent extension and how it can be customised and extended further to suit your needs.</p>
<p>Please let us know what you think below, if you have any comments, questions or corrections &#8211; we&#8217;d be happy to hear from you!</p>]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2013/02/localising-sencha-touch-and-ext-js-applications-with-ux-locale-manager/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Announcing SwarmOnline’s New Website!</title>
		<link>http://www.swarmonline.com/2013/02/announcing-swarmonlines-new-website/</link>
		<comments>http://www.swarmonline.com/2013/02/announcing-swarmonlines-new-website/#comments</comments>
		<pubDate>Thu, 07 Feb 2013 04:29:10 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1714</guid>
		<description><![CDATA[Today marks the day we launch SwarmOnline&#8217;s new website which has been in progress for the last [...]]]></description>
				<content:encoded><![CDATA[Today marks the day we launch SwarmOnline&#8217;s new website which has been in progress for the last month or two. The new website showcases SwarmOnline&#8217;s fantastic work on various mobile applications; applications; a technical book and several Open Source projects.</p>
<p>2013 is looking to be a very exciting year for SwarmOnline and we would like to thank all of our previous and current clients for making this possible. We have many new things in the pipeline and hope to be able to share these with you all very soon!</p>
<p>For now, enjoy the website and please don&#8217;t hesitate to get in touch if you want to discuss your project or if you have any questions!</p>
<p>&nbsp;</p>
<p>- <a href="mailto:info@swarmonline.com">info@swarmonline.com</a>]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2013/02/announcing-swarmonlines-new-website/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Constructing a complex form layout with Ext JS 4</title>
		<link>http://www.swarmonline.com/2012/12/constructing-a-complex-form-layout-with-ext-js-4/</link>
		<comments>http://www.swarmonline.com/2012/12/constructing-a-complex-form-layout-with-ext-js-4/#comments</comments>
		<pubDate>Mon, 10 Dec 2012 20:23:22 +0000</pubDate>
		<dc:creator>Andrew Duncan</dc:creator>
				<category><![CDATA[Development Tips]]></category>
		<category><![CDATA[Ext JS]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1541</guid>
		<description><![CDATA[In previous releases of Ext JS complicated form layouts were quite difficult to achieve. This was due [...]]]></description>
				<content:encoded><![CDATA[In previous releases of Ext JS complicated form layouts were quite difficult to achieve. This was due to the nature of the FormLayout, which was required to display labels and error messages correctly, and how it had to be combined with other nested layouts.</p>
<div class="message message-information mb-20"><p>This article is an adapted excerpt of the <a title="Ext JS 4 Book" href="http://www.packtpub.com/sencha-ext-js-4-web-application-development-cookbook/book" target="_blank">Ext JS 4 Web Application Development Cookbook</a>.</p></div>
<p>&nbsp;</p>
<p><span id="more-1541"></span></p>
<p>Ext JS 4 takes a different approach and utilizes the Ext.form.Labelable mixin, which allows form fields to be decorated with labels and error messages without requiring a specific layout to be applied to the container. This means we can combine all of the layout types the framework has to offer (which are discussed in detail in Chapter 3, Laying Out your Components) without having to overnest components in order to satisfy the form field&#8217;s layout requirements.</p>
<p>We will describe how to create a complex form using multiple, nested layouts and demonstrate how easy it is to get a form to look exactly as we want. Our example will take the structure of a Support Ticket Request form and, once we are finished, it will look like the following screenshot:</p>
<p><img class="alignnone " title="Complex Form Layout" alt="" src="http://www.swarmonline.com/wp-content/uploads/2012/12/6860_05_01.png" width="533" height="411" /></p>
<h2>How to do it&#8230;</h2>
<p>1. We start this recipe by creating a simple form panel that will contain all of the layout containers and their fields:</p>
[javascript]
var formPanel = Ext.create(&#8216;Ext.form.Panel&#8217;, {<br />
    title: &#8216;Support Ticket Request&#8217;,<br />
    width: 650,<br />
    height: 500,<br />
    renderTo: Ext.getBody(),<br />
    style: &#8216;margin: 50px&#8217;,<br />
    items: []
});<br />
[/javascript]
<p>2. Now, we will create our first set of fields—the FirstName and LastName fields. These will be wrapped in an Ext.container.Container component, which is given an hbox layout so our fields appear next to each other on one line:</p>
[javascript]
var formPanel = Ext.create(&#8216;Ext.form.Panel&#8217;, {<br />
    title: &#8216;Support Ticket Request&#8217;,<br />
    width: 650,<br />
    height: 500,<br />
    renderTo: Ext.getBody(),<br />
    style: &#8216;margin: 50px&#8217;,<br />
    items: [{<br />
        xtype: 'container',<br />
        layout: 'hbox',<br />
        items: [{<br />
            xtype: 'textfield',<br />
            fieldLabel: 'First Name',<br />
            name: 'FirstName',<br />
            labelAlign: 'top',<br />
            cls: 'field-margin',<br />
            flex: 1<br />
        }, {<br />
            xtype: 'textfield',<br />
            fieldLabel: 'Last Name',<br />
            name: 'LastName',<br />
            labelAlign: 'top',<br />
            cls: 'field-margin',<br />
            flex: 1<br />
       }]
    }]
});<br />
[/javascript]
<p>3. We have added a CSS class (field-margin) to each field, to provide some spacing between them. We can now add this style inside &lt;style&gt; tags in the head of our document:</p>
[css]
[/css]
<p>4. Next, we create a container with a column layout to position our e-mail address and telephone number fields. We nest our telephone number fields in an Ext.form.FieldContainer class, which we will discuss later in the recipe:</p>
[javascript]
items: [<br />
    ...<br />
    {<br />
        xtype: 'container',<br />
        layout: 'column',<br />
        items: [{<br />
            xtype: 'textfield',<br />
            fieldLabel: 'Email Address',<br />
            name: 'EmailAddress',<br />
            labelAlign: 'top',<br />
            cls: 'field-margin',<br />
            columnWidth: 0.6<br />
        }, {<br />
            xtype: 'fieldcontainer',<br />
            layout: 'hbox',<br />
            fieldLabel: 'Tel. Number',<br />
            labelAlign: 'top',<br />
            cls: 'field-margin',<br />
            columnWidth: 0.4,<br />
            items: [{<br />
                xtype: 'textfield',<br />
                name: 'TelNumberCode',<br />
                style: 'margin-right: 5px;',<br />
                flex: 2<br />
           }, {<br />
                xtype: 'textfield',<br />
                name: 'TelNumber',<br />
                flex: 4<br />
           }]
        }]
    }<br />
    &#8230;<br />
]
[/javascript]
<p>5. The text area and checkbox group are created and laid out in a similar way to the previous sets, by using an hbox layout:</p>
[javascript]
items: [<br />
    ...<br />
    {<br />
        xtype: 'container',<br />
        layout: 'hbox',<br />
        items: [{<br />
            xtype: 'textarea',<br />
            fieldLabel: 'Request Details',<br />
            name: 'RequestDetails',<br />
            labelAlign: 'top',<br />
            cls: 'field-margin',<br />
            height: 250,<br />
            flex: 2<br />
        }, {<br />
            xtype: 'checkboxgroup',<br />
            name: 'RequestType',<br />
            fieldLabel: 'Request Type',<br />
            labelAlign: 'top',<br />
            columns: 1,<br />
            cls: 'field-margin',<br />
            vertical: true,<br />
            items: [{<br />
                boxLabel: 'Type 1',<br />
                name: 'type1',<br />
                inputValue: '1'<br />
            }, {<br />
                boxLabel: 'Type 2',<br />
                name: 'type2',<br />
                inputValue: '2'<br />
            }, {<br />
                boxLabel: 'Type 3',<br />
                name: 'type3',<br />
                inputValue: '3'<br />
            }, {<br />
                boxLabel: 'Type 4',<br />
                name: 'type4',<br />
                inputValue: '4'<br />
            }, {<br />
                boxLabel: 'Type 5',<br />
                name: 'type5',<br />
                inputValue: '5'<br />
            }, {<br />
                boxLabel: 'Type 6',<br />
                name: 'type6',<br />
                inputValue: '6'<br />
            }],<br />
            flex: 1<br />
        }]
    }<br />
    &#8230;<br />
]
[/javascript]
<p>6.Finally, we add the last field, which is a file upload field, to allow users to provide attachments:</p>
[javascript]
items: [<br />
    ...<br />
    {<br />
        xtype: 'filefield',<br />
        cls: 'field-margin',<br />
        fieldLabel: 'Attachment',<br />
        width: 300<br />
    }<br />
    ...<br />
]
[/javascript]
<h2>All together now&#8230;</h2>
<p>This code snippet is a concatenation of the above seven steps.</p>
[javascript]
<p>        1. Constructing a complex form layout<br />
        &lt;!&#8211; Library Files &#8211;&gt;<br />
&lt;script type=&quot;text/javascript&quot; src=&quot;../../ext-all-debug.js&quot;&gt;&lt;/script&gt;&lt;script type=&quot;text/javascript&quot;&gt;// &lt;![CDATA[<br />
            Ext.onReady(function(){</p>
<p>                var formPanel = Ext.create('Ext.form.Panel', {<br />
                    title: 'Support Ticket Request',<br />
                    width: 650,<br />
                    height: 500,<br />
                    renderTo: Ext.getBody(),<br />
                    style: 'margin: 50px', // move panel off browser's edge<br />
                    items: [{<br />
                        xtype: 'container',<br />
                        layout: 'hbox',<br />
                        items: [{<br />
                            xtype: 'textfield',<br />
                            fieldLabel: 'First Name',<br />
                            name: 'FirstName',<br />
                            labelAlign: 'top',<br />
                            cls: 'field-margin',<br />
                            flex: 1<br />
                        }, {<br />
                            xtype: 'textfield',<br />
                            fieldLabel: 'Last Name',<br />
                            name: 'LastName',<br />
                            labelAlign: 'top',<br />
                            cls: 'field-margin',<br />
                            flex: 1<br />
                        }]
                    }, {<br />
                        xtype: &#8216;container&#8217;,<br />
                        layout: &#8216;column&#8217;,<br />
                        items: [{<br />
                            xtype: 'textfield',<br />
                            fieldLabel: 'Email Address',<br />
                            name: 'EmailAddress',<br />
                            labelAlign: 'top',<br />
                            cls: 'field-margin',<br />
                            columnWidth: 0.6<br />
                        }, {<br />
                            xtype: 'fieldcontainer',<br />
                            layout: 'hbox',<br />
                            fieldLabel: 'Tel. Number',<br />
                            labelAlign: 'top',<br />
                            cls: 'field-margin',<br />
                            columnWidth: 0.4,<br />
                            items: [{<br />
                                xtype: 'textfield',<br />
                                name: 'TelNumberCode',<br />
                                style: 'margin-right: 5px;',<br />
                                flex: 2<br />
                            }, {<br />
                                xtype: 'textfield',<br />
                                name: 'TelNumber',<br />
                                flex: 4<br />
                            }]
                        }]
                    }, {<br />
                        xtype: &#8216;container&#8217;,<br />
                        layout: &#8216;hbox&#8217;,<br />
                        items: [{<br />
                            xtype: 'textarea',<br />
                            fieldLabel: 'Request Details',<br />
                            name: 'RequestDetails',<br />
                            labelAlign: 'top',<br />
                            cls: 'field-margin',<br />
                            height: 250,<br />
                            flex: 2<br />
                        }, {<br />
                            xtype: 'checkboxgroup',<br />
                            name: 'RequestType',<br />
                            fieldLabel: 'Request Type',<br />
                            labelAlign: 'top',<br />
                            columns: 1,<br />
                            cls: 'field-margin',<br />
                            vertical: true,<br />
                            items: [{<br />
                                boxLabel: 'Type 1',<br />
                                name: 'type1',<br />
                                inputValue: '1'<br />
                            }, {<br />
                                boxLabel: 'Type 2',<br />
                                name: 'type2',<br />
                                inputValue: '2'<br />
                            }, {<br />
                                boxLabel: 'Type 3',<br />
                                name: 'type3',<br />
                                inputValue: '3'<br />
                            }, {<br />
                                boxLabel: 'Type 4',<br />
                                name: 'type4',<br />
                                inputValue: '4'<br />
                            }, {<br />
                                boxLabel: 'Type 5',<br />
                                name: 'type5',<br />
                                inputValue: '5'<br />
                            }, {<br />
                                boxLabel: 'Type 6',<br />
                                name: 'type6',<br />
                                inputValue: '6'<br />
                            }],<br />
                            flex: 1<br />
                        }]
                    }, {<br />
                        xtype: &#8216;filefield&#8217;,<br />
                        cls: &#8216;field-margin&#8217;,<br />
                        fieldLabel: &#8216;Attachment&#8217;,<br />
                        width: 300<br />
                    }]
                });</p>
<p>            });</p>
<p>// ]]&gt;&lt;/script&gt;</p>
[/javascript]
<h2>How it works&#8230;</h2>
<p>All Ext JS form fields inherit from the base Ext.Component class and so can be included in all of the framework&#8217;s layouts. For this reason, we can include form fields as children of containers with layouts (such as hbox and column layouts) and their position and size will be calculated accordingly.</p>
<div>
<div class="message message-information mb-20"><p><strong>Upgrade Tip:</strong> Ext JS 4 does not have a form layout meaning a level of nesting can be removed and the form fields&#8217; labels will still be displayed correctly by just specifying the fieldLabel config.</p></div>
</div>
<p>The Ext.form.FieldContainer class used in Step 3 is a special component that allows us to combine multiple fields into a single container, which also implements the Ext.form.Labelable mixin. This allows the container itself to display its own label that applies to all of its child fields while also giving us the opportunity to configure a layout for its child components.]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2012/12/constructing-a-complex-form-layout-with-ext-js-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cook up some Ext JS 4 recipes for free this weekend!</title>
		<link>http://www.swarmonline.com/2012/09/cook-up-some-ext-js-4-recipes-for-free-this-weekend/</link>
		<comments>http://www.swarmonline.com/2012/09/cook-up-some-ext-js-4-recipes-for-free-this-weekend/#comments</comments>
		<pubDate>Fri, 28 Sep 2012 10:18:09 +0000</pubDate>
		<dc:creator>Andrew Duncan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1566</guid>
		<description><![CDATA[Packt Publishing are celebrating their 1000th book this week and are offering a free eBook for everyone! [...]]]></description>
				<content:encoded><![CDATA[Packt Publishing are celebrating their 1000th book this week and are offering a free eBook for everyone! This includes the <a title="Ext JS 4 Cookbook" href="http://www.swarmonline.com/2012/08/ext-js-4-web-application-development-cookbook-released/">Ext JS 4 Web Application Development Cookbook</a> which we released last month!</p>
<p>You&#8217;ll need to hurry because the offer is only available from 28-30th September 2012.</p>
<p>Click <a href="http://bit.ly/RXnAMc">http://bit.ly/RXnAMc</a> to for more information and start building apps with Sencha&#8217;s Ext JS 4 Framework today!</p>
<p><span id="more-1566"></span></p>
<h2>Official Statement from Packt Publishing:</h2>
<p>28<sup>th</sup> September 2012</p>
<p><strong>Packt Publishing reaches 1000 IT titles and celebrates with an open invitation</strong></p>
<p>Birmingham-based IT publisher <a href="http://www.packtpub.com/">Packt Publishing</a> is about to publish its 1000<sup>th</sup> title. Packt books are renowned among developers for being uniquely practical and focused, but you’d be forgiven for not yet being in the know – Packt books cover highly specific tools and technologies which you might not expect to see a high quality book on.</p>
<p>Packt is certain that in its 1000 titles there is at least one book that everyone in IT will find useful right away, and are inviting anyone to choose and download any one of its eBooks for free over its celebration weekend of 28-30<sup>th</sup> Sep 2012. Packt is also opening its online library for a week for free to give customers an easy to way to research their choice of free eBook.</p>
<p>Packt supports many of the Open Source projects covered by its books through a project royalty donation, which has contributed over $400,000 to Open Source projects up to now. As part of the celebration Packt is allocating $30,000 to share between projects and authors as part of the weekend giveaway, allocated based on the number of copies of each title downloaded.</p>
<p>Dave Maclean, founder of Packt Publishing:</p>
<p><strong>“At Packt we set out 8 years ago to bring practical, up to date and easy to use technical books to the specialist tools and technologies that had been largely overlooked by IT publishers. Today, I am really proud that with our authors and partners we have been able to make useful books available on over 1000 topics and make our contribution to the development community.”</strong>]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2012/09/cook-up-some-ext-js-4-recipes-for-free-this-weekend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ext JS 4 Web Application Development Cookbook Released</title>
		<link>http://www.swarmonline.com/2012/08/ext-js-4-web-application-development-cookbook-released/</link>
		<comments>http://www.swarmonline.com/2012/08/ext-js-4-web-application-development-cookbook-released/#comments</comments>
		<pubDate>Fri, 31 Aug 2012 08:11:15 +0000</pubDate>
		<dc:creator>Andrew Duncan</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Web Design & Development Blog]]></category>
		<guid isPermaLink="false">http://www.swarmonline.com/?p=1528</guid>
		<description><![CDATA[It gives the two of us great pleasure to announce the release of our writing efforts over [...]]]></description>
				<content:encoded><![CDATA[<strong>It gives the two of us great pleasure to announce the release of our writing efforts over the past year.</strong></p>
<p>Packed with over 100 easy to follow recipes which demonstrate, through real life examples, numerous features of Ext JS 4. This book will help you create anything from basic components to advanced web applications using Sencha’s unrivalled Ext JS framework.</p>
<h2>Sample Chapter</h2>
<p><a href="http://www.packtpub.com/sencha-ext-js-4-web-application-development-cookbook/book" target="_blank">Packt Publishing</a> have made available a chapter of the book which you can download for free. <a title="Sample Chapter Download" href="http://www.packtpub.com/sites/default/files/9781849516860-Chapter-05.pdf" target="_blank">Chapter 5 &#8211; Loading, Submitting and Validating Forms</a> explores the topic of forms with Ext JS 4. We begin the chapter by creating a support-ticket form in the first recipe which we use throughout.</p>
<p>Instead of focusing on how to configure specific fields (see Chapter 6), we demonstrate more generic tasks for working with forms. Specifically, these are populating forms, submitting forms, performing client-side validation, and handling callbacks/exceptions.</p>
<p><span id="more-1528"></span></p>
<p>Download the sample chapter directly from <a title="Ext JS 4 Cookbook Sample Chapter" href="http://www.packtpub.com/sites/default/files/9781849516860-Chapter-05.pdf" target="_blank">Packt Publishing</a>.</p>
<h2>Additional Content</h2>
<p>In addition to the content in the book we have prepared an appendix with a further 20 recipes!</p>
<p><strong>&#8220;Ext JS 4 Cookbook &#8211; Exploring Further&#8221;</strong> takes a look at a range of other useful topics that we weren&#8217;t able to fit in the book. Here we cover:</p>
<ol>
<li>Creating your Applications Folder Structure</li>
<li>Encoding &amp; Decoding HTML Strings</li>
<li>Detecting Available Browser Features</li>
<li>Evaluating Object Types and Values</li>
<li>Presenting Tabular Data with the TableLayout</li>
<li>Absolutely Positioning Components</li>
<li>Positioning Panel Headers</li>
<li>Animated filtering of a DataView</li>
<li>Specifying a form field&#8217;s length limits</li>
<li>Displaying validation alerts to the User</li>
<li>Dynamically generate forms from loaded JSON</li>
<li>Positioning Field Labels</li>
<li>Configuring a grid from MetaData</li>
<li>Combining several Chart types into one</li>
<li>Displaying detailed information when hovering over charts</li>
<li>Persisting User Interface State</li>
<li>Retaining support for the browser back button</li>
<li>Using Ext Direct with Grids</li>
<li>Handling Exceptions with Ext Direct</li>
<li>Handling session timeouts with a TaskManager</li>
</ol>
<div>When we have more information on how this can be accessed we&#8217;ll update this page.</div>
<h2>Synopsis</h2>
<p><a href="http://www.packtpub.com/sencha-ext-js-4-web-application-development-cookbook/book" target="_blank"><img class="alignright" title="Ext JS 4 Cookbook Cover" src="http://www.swarmonline.com/wp-content/uploads/2011/10/6860OS_mockupcover_cb-243x300.jpg" alt="Ext JS 4 Web Application Development Cookbook" width="243" height="300" /></a><strong>Ext JS 4</strong> is Sencha’s latest JavaScript framework for developing cross-platform web applications. Built upon web standards, Ext JS provides a comprehensive library of user interface widgets and data manipulation classes to turbo-charge your application’s development. Ext JS 4 builds on Ext JS 3, introducing a number of new widgets and features including the popular MVC architecture, easily customisable themes and plugin-free charting.</p>
<p><a href="http://www.packtpub.com/sencha-ext-js-4-web-application-development-cookbook/book" target="_blank"><em>Ext JS 4 Web Application Development Cookbook</em></a> works through the framework from the fundamentals to advanced features and application design. More than 130 detailed and practical recipes demonstrate all of the key widgets and features the framework has to offer. With this book, and the Ext JS framework, learn how to develop truly interactive and responsive web applications.</p>
<p>Starting with the framework fundamentals, you will work through all of the widgets and features the framework has to offer, finishing with extensive coverage of application design and code structure.</p>
<p>Over 130 practical and detailed recipes describe how to create and work with forms, grids, data views, and charts. You will also learn about the best practices for structuring and designing your application and how to deal with storing and manipulating data. The cookbook structure is such that you may read the recipes in any order.</p>
<p><a href="http://www.packtpub.com/sencha-ext-js-4-web-application-development-cookbook/book" target="_blank">The <em>Ext JS 4 Web Application Development Cookbook</em></a> will provide you with the knowledge to create interactive and responsive web applications, using real life examples.</p>
<p><strong>What you will learn from this book :</strong></p>
<ul>
<li>Structure your application according to best practices, manipulate the DOM, and handle events raised by users and the framework</li>
<li>Learn the layouts available in Ext JS and understand how to combine these to make complex layouts</li>
<li>Create aesthetic and user-friendly forms, validate these on the client, and submit data to your server</li>
<li>Present and organize data with Trees, Tabbed layouts, Data Views, and Templates</li>
<li>Make AJAX requests, model data objects, incorporate Ext.Direct, perform CRUD operations on data, and integrate HTML5 local storage with Ext JS</li>
<li>Work with Grids to present and manipulate tabular data by editing rows, dragging and dropping records, scrolling infinitely, and grouping data</li>
<li>Represent data visually with flexible and interactive Charts and Drawing components</li>
<li>Customize the look and feel of your application with SASS and Compass</li>
<]]></content:encoded>
			<wfw:commentRss>http://www.swarmonline.com/2012/08/ext-js-4-web-application-development-cookbook-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
