<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>
      <title>Titanium Developers AppTitans</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=6d700ffd24a9b9d776bab0cd0205d1b5</link>
      <atom:link rel="next" href="http://pipes.yahoo.com/pipes/pipe.run?_id=6d700ffd24a9b9d776bab0cd0205d1b5&amp;_render=rss&amp;page=2"/>
      <pubDate>Tue, 18 Jun 2013 06:25:59 +0000</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>Announcing Titanium 3.1.1 Production Release</title>
         <link>http://developer.appcelerator.com/blog/2013/06/announcing-titanium-3-1-1-production-release.html</link>
         <description>I am pleased to announce the general availability of our latest Titanium release, version 3.1.1.  In this minor release we addressed over 125 bugs fixes and included several enhancements. For a full list of all changes and improvements in this release, please read the release notes. Android Enhancements Google Maps v2  Support “userLocationButton” property Allows developers to [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21251</guid>
         <pubDate>Mon, 17 Jun 2013 22:22:43 +0000</pubDate>
         <content:encoded><![CDATA[<p>I am pleased to announce the general availability of our latest Titanium release, version 3.1.1.  In this minor release we addressed over 125 bugs fixes and included several enhancements. For a full list of all changes and improvements in this release, please read the <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/titanium/release-notes/?version=3.1.1.GA">release notes</a>.</p>
<h3>Android Enhancements</h3>
<ul>
<li>Google Maps v2
<ul>
<li> Support “userLocationButton” property
<ul>
<li>Allows developers to turn on/off the user location button.</li>
</ul>
</li>
<li> Support “regionchanged” event
<ul>
<li>Provides the delta of the latitude and longitude.</li>
</ul>
</li>
<li>Support “isGooglePlayServicesAvailable”
<ul>
<li>Allow developers to determine if Google Play Services are available for the app</li>
</ul>
</li>
</ul>
</li>
<li>Camera
<ul>
<li>Support “savePhotoToGallery” property. Previously, photos were automatically stored in the gallery. This property gives you the control to store or not store the photos.</li>
</ul>
</li>
</ul>
<h3>BlackBerry Beta</h3>
<p>This release also includes the latest version of our BlackBerry SDK beta, with integrated Studio support for creating and running BlackBerry apps.</p>
<h3>Changes That Require Your Attention</h3>
<ul>
<li>Android SDK 2.3.3
<ul>
<li>We have increased the minimum Android SDK support from 2.2 to 2.3.3.</li>
</ul>
</li>
<li>iOS 5.x
<ul>
<li>We have increased the minimum supported version of iOS from 4.3.x to 5.x.</li>
</ul>
</li>
<li>Change of the calendar namespace
<ul>
<li>If you are using the calendar in Android our namespace has changed from Titanium.Android.Calendar to Titanium.Calendar. This means that you will have to change any areas of your code referencing Titanium.Android.Calendar to Titanium.Calendar.</li>
</ul>
</li>
</ul>
<h3>Downloading 3.1.1</h3>
<p>For new users, download Titanium 3.1.1 by clicking <a rel="nofollow" title="Signup for Titanium" target="_blank" href="https://my.appcelerator.com/auth/signup">here</a>.</p>
<p>For existing Titanium Studio users, you will be prompted to update automatically on the next restart. You can also manually check for updates by selecting the “Check for Titanium SDK Updates” from the “Help” menu within Titanium Studio.</p>
<p><strong>If you previously installed the Release Candidate versions of the Titanium CLI and Alloy</strong>, that is, <em>npm install titanium@3.1.1-cr</em>, or any -beta or -cr packages, you need to first uninstall these components before installing or updating to 3.1.1.GA. The <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/titanium/release-notes/?version=3.1.1.GA">release notes</a> contain specific instructions on how to do so.</p>
<p>As always I want to thank our 470,000 strong community of developers for your constant feedback and support.</p>]]></content:encoded>
      </item>
      <item>
         <title>Upcoming ACS changes: user session and geo query</title>
         <link>http://developer.appcelerator.com/blog/2013/06/upcoming-acs-changes-user-session-and-geo-query.html</link>
         <description>We try to be as transparent as possible about important changes that could impact your development. To that end, we are planning to roll out two ACS changes in next couple of months that may impact your application. Application User Session Expiration An application user session never expires today.  We are introducing the policy of [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21209</guid>
         <pubDate>Wed, 12 Jun 2013 05:56:42 +0000</pubDate>
         <content:encoded><![CDATA[<p>We try to be as transparent as possible about important changes that could impact your development. To that end, we are planning to roll out two ACS changes in next couple of months that may impact your application.</p>
<h3><strong>Application User Session Expiration</strong></h3>
<p>An application user session never expires today.  We are introducing the policy of expiring and removing sessions that have been inactive for 6 months.</p>
<p>How does it affect your application?  If your application logins a user and saves the session_id, normally stored in a cookie, every time it makes a <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/cloud/latest/#!/api">REST call</a> to ACS using the same session_id, the expiry clock is reset and the user gets another 6 months. As long as the ACS user is active using the same session_id within 6 months, there is no impact on your application and current logged in user. If an application user is completely inactive for 6 months or more, this user session is removed and any subsequent ACS call that requires user login such as create.json, update.json and delete.json will get a 404 error. We recommend your application can handle an invalid user session error and prompts a login screen to the user to login again.</p>
<h3><span style="font-size:1.17em;">Geo Query</span></h3>
<p>ACS also currently supports MongoDB’s <a rel="nofollow" target="_blank" href="http://docs.mongodb.org/manual/reference/operator/nearSphere/">$nearSphere</a> Geo Query.  Geo Query requires a field to be indexed with a geo index.  The ACS fields you can perform $nearSphere on are <em>lnglat</em> (pre-defined location data and only available in <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/cloud/latest/#!/api/Places">places</a> and <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/cloud/latest/#!/api/Events">events</a>) and <em>coordinates</em> (list of custom defined location data and available in all objects).  It implies that places and events have two geo indexes in the same collection and that prevents us from supporting <a rel="nofollow" target="_blank" href="http://docs.mongodb.org/manual/reference/command/geoNear/">$geoNear</a> operation that is more powerful than $nearSphere.  We will consolidate <em>lnglat</em> value with <em>coordinates</em> values and remove geo index on <em>lnglat</em> field.</p>
<p>How does it affect your application?  For events and places, even if you never explicitly copied <em>lnglat</em> value to coordinates, <em>lnglat</em> will appear as the first element of <em>coordinates</em>.  Performing $nearSphere on <em>coordinates</em> field will return a match if it matches the <em>lnglat</em> value.  $nearSphere query on <em>lnglat</em> or <em>coordinates</em> will continue to work as before.</p>
<h3>Questions?</h3>
<p>Please post your questions on Appcelerator <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/questions/tag/acs">Q&amp;A forum</a> with &#8220;ACS&#8221; tag or leave your comments on this blog post.</p>]]></content:encoded>
      </item>
      <item>
         <title>Building a custom front-end to ACS using Node.ACS [Part 2]</title>
         <link>http://developer.appcelerator.com/blog/2013/06/building-a-custom-front-end-to-acs-using-node-acs-part-2.html</link>
         <description>On my previous post we went through the process of setting up a Node.ACS app, and understanding the basics of its built-in MVC framework. It&amp;#8217;s now time to integrate ACS back-end services. Our main goal for this mini-project is to use a responsive framework (Bootstrap) to provide a custom, clutter-free front-end for ACS. Think about [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21121</guid>
         <pubDate>Tue, 11 Jun 2013 21:47:23 +0000</pubDate>
         <content:encoded><![CDATA[<style>
.appc_code{
background-color:#000;color:#f2f2f2;padding:5px;margin:5px;}
</style>
<p>On my <a rel="nofollow">previous post</a> we went through the process of setting up a Node.ACS app, and understanding the basics of its built-in MVC framework. It&#8217;s now time to integrate ACS back-end services. Our main goal for this mini-project is to use a responsive framework (<a rel="nofollow" target="_blank" href="http://twitter.github.io/bootstrap/">Bootstrap</a>) to provide a custom, clutter-free front-end for ACS. Think about it this way: You&#8217;re using ACS to store locations. Why give your client access to ALL of ACS, just to curate data? ACS&#8217; interface is designed for the developer, not for the end-user. We&#8217;ll build a phone and tablet-friendly web user interface what will allow them to easily enter data into the system. So let&#8217;s get started!</p>
<h2>Structure of our website:</h2>
<p><center><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/nodeacs3.png" alt=""/></center></p>
<p>We&#8217;ll have a Login screen that will be used to login against the ACS User service. Upon successful login, the user will see a screen displaying a list of places that will be part of the ACS Places service. This screen will provide options for Adding and Deleting places, as well as launching a &#8220;Google Map&#8221; when a location is clicked. On the top navigation area we&#8217;ll have two links, About and Contact with sample content only to illustrate linking and session management. The website will look like this:</p>
<p><center><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/nodeacs4.png" alt=""/></center></p>
<h2>App.js</h2>
<p>In this file you initialize your website and your session with ACS.</p>
<div class="appc_code">
<pre>var ACS = require('acs').ACS;
var ACS_KEY='YOUR_ACS_KEY';
var ACS_SECRET='YOUR_ACS_SECRET';

// initialize app
function start(app, express) {
     app.use(express.favicon(__dirname + '/public/images/favicon.ico'));          //set favicon

     // this line is explained @
     // http://docs.appcelerator.com/cloud/latest/#!/guide/node_mvc
     app.use(express.session({ key: 'node.acs', secret: ACS_SECRET }));

     ACS.init(ACS_KEY, ACS_SECRET);
}</pre>
</div>
<h2>Config.json</h2>
<div class="appc_code">
<pre>{
  "routes":
  [
    { "path": "/", "callback": "application#index" },
    { "path": "/error", "callback": "application#error" },
    { "path": "/home", "callback": "home#home" },
    { "path": "/login", "method":"post", "callback": "useraccess#login" },
    { "path": "/logoff", "callback": "useraccess#logoff" },
    { "path": "/about", "callback": "application#about" },
    { "path": "/contact", "callback": "application#contact" },
    { "path": "/api/delete", "callback": "api#deleterec" },
    { "path": "/api/addplace", "method":"post","callback": "api#addrec" }
  ],
  "filters":
  [
    {"path": "/home", "callback": "session_filter#validateSession"},
    {"path": "/about", "callback": "session_filter#validateSession"},
    {"path": "/contact", "callback": "session_filter#validateSession"},
    {"path": "/api/delete", "callback": "session_filter#validateSession"},
    {"path": "/api/add", "callback": "session_filter#validateSession"}
  ],
  "websockets":
  [
    { "event": "", "callback": ""}
  ]
}</pre>
</div>
<p>This file is in many ways the heart of your app. Here you define how the user is allowed to interact with the website, or how a page should interact with another. The first section, the routes, are a fundamental part of an MVC website. Defining this section is part of your website planning process and provides you a clear idea of how your website will behave.</p>
<table style="border:1px solid;" width="75%">
<thead>
<tr>
<th>Path</th>
<th>Method</th>
<th>File</th>
<th>Function</th>
</tr>
<tr>
<td>/</td>
<td>GET</td>
<td>application</td>
<td>index</td>
</tr>
<tr>
<td>/error</td>
<td>GET</td>
<td>application</td>
<td>error</td>
</tr>
<tr>
<td>/home</td>
<td>GET</td>
<td>home</td>
<td>home</td>
</tr>
<tr>
<td>/login</td>
<td>POST</td>
<td>useraccess</td>
<td>login</td>
</tr>
<tr>
<td>/logoff</td>
<td>GET</td>
<td>useraccess</td>
<td>logoff</td>
</tr>
<tr>
<td>/about</td>
<td>GET</td>
<td>application</td>
<td>about</td>
</tr>
<tr>
<td>/contact</td>
<td>GET</td>
<td>application</td>
<td>contact</td>
</tr>
<tr>
<td>/api/delete</td>
<td>GET</td>
<td>api</td>
<td>deleterec</td>
</tr>
<tr>
<td>/api/addplace</td>
<td>POST</td>
<td>api</td>
<td>addrec</td>
</tr>
</thead>
</table>
<p>&nbsp;</p>
<p>I have stored functions in different files, but only for organization purposes. This is more an issue of your personal programming style. You can certainly use a single file for all your functions. This table should be read like: When the user browses to /home, I will execute the home function inside /controllers/home.js and the data will be available via GET.</p>
<p>Now let&#8217;s look at the filters section, which has a similar format.</p>
<table style="border:1px solid;" width="75%">
<thead>
<tr>
<th>Path</th>
<th>File</th>
<th>Function</th>
</tr>
<tr>
<td>/home</td>
<td>session_filter</td>
<td>validateSession</td>
</tr>
<tr>
<td>/about</td>
<td>session_filter</td>
<td>validateSession</td>
</tr>
<tr>
<td>/contact</td>
<td>session_filter</td>
<td>validateSession</td>
</tr>
<tr>
<td>/api/delete</td>
<td>session_filter</td>
<td>validateSession</td>
</tr>
<tr>
<td>/api/add</td>
<td>session_filter</td>
<td>validateSession</td>
</tr>
</thead>
</table>
<p>All entries are using the same function inside the same file. This block is actually providing a way for us to protect certain areas of our website. Instead of having to validate the user session by code on every page, we set a filter on the pages we want to protect. The validateSession function simply verifies the validity of the session. If invalid redirects to error page, if valid, control is returned to the page controller.</p>
<div class="appc_code">
<pre>
function validateSession(req, res, next) {
  if(!req.session.session_id) {
    res.redirect('/error');
  } else {
    next();
  }
}
</pre>
</div>
<h2>ACS</h2>
<p>Access to ACS methods is consistent with <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2013/05/using-acs-as-a-back-end-for-your-app.html">the way you&#8217;d used them with Titanium</a>, where you call the method and pass an object and a callback.</p>
<p>For our login method, we grab data from the HTTP POST and then send to ACS.</p>
<div class="appc_code">
<pre>
function login(req,res){
    ACS.Users.login({
        // grab data from http post
        login: req.body.username,
        password: req.body.password
    }, function(data) {
    	if (data.success){
    		// set session data to be used later througout the app
		req.session.session_id=data.meta.session_id;
                req.session.user_id=data.users[0].id;
		req.session.fullname=data.users[0].first_name + ' ' +
data.users[0].last_name;
                // the "home" controller will pick it up
		res.redirect('/home');
    	}else{
    		res.redirect('/error');
    	}
    });
}
</pre>
</div>
<p>When the user successfully logs in, he/she is taken to Home, where a list of Places is displayed. The controller for the &#8220;Home&#8221; template looks like this:</p>
<div class="appc_code">
<pre>
function home(req, res) {
	ACS.Places.query({
        order: "-created_at" // new on top
    }, function(data) {
        if(data.success) {
            console.log(data);
            res.render('home', {
                                title: 'Beer Places',
                                places:data.places,
                                page:'Home',
                                fullname:req.session.fullname
                                });
        } else {
            res.send('Error occured. Error code: ' + data.error + '.
Message: ' + data.message);
        }
    })
}
</pre>
</div>
<p>The line that reads <strong>res.render(&#8216;home&#8217;,{})</strong> is sending some data to the View, and one of these pieces is the actual places array that was returned by ACS. This Array is send as a static, client-side array to the view. The templating engine can now loop through the array and write the rows in HTML.</p>
<div class="appc_code">
<pre>
&lt;tbody&gt;
&lt;% places.forEach(function(place){ %&gt;
  &lt;tr id="&lt;%=place.id%&gt;"&gt;
    &lt;td&gt;&lt;%=place.name%&gt;&lt;/td&gt;
    &lt;td&gt;&lt;%=place.city%&gt;&lt;/td&gt;
    &lt;td&gt;&lt;%=place.phone_number%&gt;&lt;/td&gt;
    &lt;td&gt;&lt;a href="http://maps.google.com/?q=&lt;%=place.name%&gt;@
&lt;%=place.latitude%&gt;,&lt;%=place.longitude%&gt;" target="_blank"
title="Map"&gt;Map&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;a href="javascript:void(0);" onClick="deleterec('&lt;%=place.id%&gt;')"
title="Delete"&gt;&lt;div style="text-align: center"&gt;
&lt;i class="icon-remove-circle"&gt;&lt;/i&gt;&lt;/div&gt;&lt;/a&gt;
&lt;/td&gt;
  &lt;/tr&gt;
&lt;%    }) %&gt;
&lt;/tbody&gt;
</pre>
</div>
<p>If you look closely, you&#8217;ll see that the <strong>places</strong> array effectively is available to the template. Also notice that you can execute Javascript code by encapsulating it in <strong></strong>tags, in this case performing a forEach loop on the Places array, and displaying HTML rows. Just remember, when you want to execute Javascript code you use <strong>&lt;%= your_code %&gt;</strong> and to echo values you use <strong>&lt;% your_variable %&gt;</strong>.</p>
<h2>An API on top of an API</h2>
<p>You could use Node.ACS to provide high-level methods, an API if you like, that interact with the ACS API. An example of this technique is providing a &#8220;delete&#8221; method that in turn will call the ACS delete place method. Why do this? Well, for one, you don&#8217;t want to have your API key available in your Javascript source. With this method, your API key resides inside Node.ACS, that is in the server-side. Another reason could be because you&#8217;d like to perform other operations with the data returned by ACS, perhaps even return a new JSON string to your front-end. If you look at our Javascript code for deleting a record, it looks like this:</p>
<div class="appc_code">
<pre>
function deleterec(recid){
      var r=confirm("Delete this record?");
      if (r==true){
          $.ajax({
            url: '/api/delete/?id=' + recid,
            type: 'GET',
            success: function(data) {
              location.href='/home';
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                //alert("Status: " + textStatus);
                //alert("Error: " + errorThrown);
            }
        });
      }
    }
</pre>
</div>
<p>NOTE: In a real-world scenario you&#8217;d want to provide a more secure way of deleting your records and not by simply calling a Delete URL with your record id, but those security measures are out of the scope of this post.</p>
<p>Using Node.ACS&#8217; built-in is really fun.  The fact of not having to install a web server is a very convenient feature, and being able to take advantage of node.js definitely provides virtually endless possibilities. </p>
<p>The full source code for this example is available at <a rel="nofollow" target="_blank" href="https://github.com/ricardoalcocer/nodeacs_sample_website">https://github.com/ricardoalcocer/nodeacs_sample_website</a>, simply fork/clone, add your own ACS Key and Secret, and hack away. This is a sample/proof-of-concept so feel free to send me pull request with error corrections or features you&#8217;ve added to the project.</p>]]></content:encoded>
         <category>@en</category>
      </item>
      <item>
         <title>Support for iOS 7</title>
         <link>http://developer.appcelerator.com/blog/2013/06/support-for-ios-7.html</link>
         <description>The big news of the day at WWDC in San Francisco was the unveiling of iOS 7. Judging from the reaction, there&amp;#8217;s no reason to believe that iOS 7 won&amp;#8217;t fulfill Tim Cook&amp;#8217;s promise of being &amp;#8220;the most significant update to the mobile operating system since its introduction on the iPhone in 2007&amp;#8243;. New features [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21191</guid>
         <pubDate>Tue, 11 Jun 2013 14:49:42 +0000</pubDate>
         <content:encoded><![CDATA[<p>The big news of the day at WWDC in San Francisco was the unveiling of iOS 7.</p>
<p>Judging from the reaction, there&#8217;s no reason to believe that iOS 7 won&#8217;t fulfill Tim Cook&#8217;s promise of being &#8220;the most significant update to the mobile operating system since its introduction on the iPhone in 2007&#8243;.</p>
<p>New features in this release include:</p>
<ul>
<li>Improved controls and notifications</li>
<li>Multi-tasking interface and responsiveness to motion for apps</li>
<li>AirDrop content sharing</li>
<li>In-car integration</li>
<li>Personal security enhancements</li>
</ul>
<p>&nbsp;</p>
<p>We have already downloaded the beta and have successfully recompiled and run a few simple apps on top of it. No doubt you&#8217;ll be doing the same and looking for new and innovative ways to take advantage of these new capabilities.</p>
<p>Rest assured that we are committed to delivering support in the Appcelerator Platform and Titanium on the day it is released.</p>
<p>In the meantime, please share with us and the rest of the community your feature requests and requirements for iOS7-specific support, as well as any issues, via the Titanium Community JIRA. <a rel="nofollow" target="_blank" href="https://jira.appcelerator.org/browse/TC">https://jira. appcelerator.org/browse/TC</a></p> 
<p>Stay tuned for more information as we get closer to the general availability of iOS 7 in the fall.</p>]]></content:encoded>
         <category>@en</category>
      </item>
      <item>
         <title>Featured App Spotlight – SV Waldhof Mannheim</title>
         <link>http://developer.appcelerator.com/blog/2013/06/featured-app-spotlight-sv-waldhof-mannheim.html</link>
         <description>Today’s featured spotlight comes from Kenan Sulayman. Kenan and his team built a slick soccer app that enables users to follow multiple teams in one app and get live feeds and extensive player information on the go. Hear more about how Kenan tackled this feat using Titanium. Why did you pick Titanium for your development [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21164</guid>
         <pubDate>Mon, 10 Jun 2013 15:48:38 +0000</pubDate>
         <content:encoded><![CDATA[<p><em>Today’s featured spotlight comes from Kenan Sulayman. Kenan and his team built a <a rel="nofollow" title="SV Waldhof Mannheim" target="_blank" href="https://itunes.apple.com/de/app/sv-waldhof-mannheim/id570686656?mt=8">slick soccer app</a> that enables users to follow multiple teams in one app and get live feeds and extensive player information on the go. Hear more about how Kenan tackled this feat using Titanium.</em></p>
<hr />
<p><strong>Why did you pick Titanium for your development needs?</strong></p>
<p><img style="float:left;height:128px;padding-right:20px;" src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/waldhof_002.png" alt="Waldhof"/> Titanium is awesome. It&#8217;s open unlike other platforms and can be modified as we want, when we want.</p>
<p>We didn&#8217;t chose native SDKs because we wanted flexibility, fast development speed and extensibility; we are Javascript-gurus and have background as architects using node.js-powered Cloud-solutions. (scalable web-apps, innovative database solutions and real time communication)</p>
<p><strong>Tell us a little bit about choosing your development option</strong></p>
<p>So we had the basic concept of &#8220;that&#8221; soccer app. We asked how we could do something really innovative and beautiful, while keeping spent resources low, and creativity and flexibility at maximum.</p>
<p>There were many development options we considered, including Sencha Touch and PhoneGap. We even considered Adobe’s “Publish to iOS” feature. We explored these options because everyone on our team feared the Objective-C mess that would happen if we tried to use it in an extremely dynamic way.</p>
<p>Ultimately, this is why we chose Titanium and the ability to leverage Javascript to build solid and native experiences for mobile devices.</p>
<p><strong>Can you describe the app in more detail?</strong></p>
<p>We wanted an innovative <a rel="nofollow" title="SV Waldhof Mannheim" target="_blank" href="https://itunes.apple.com/de/app/sv-waldhof-mannheim/id570686656?mt=8">soccer app</a> that combined real-time information with user-interaction. This includes information about every player &#8211; his interests, pictures, per-game information, live-ticker, etc. and a platform on which everything could thrive.</p>
<p>We didn&#8217;t just build an app, we built an app sandbox! Titanium makes it extremely easy to customize an app so that we could not only implement several teams into one app, but also have the opportunity to easily extend the app to be a white-label product: this allows us to build unique experiences for as many teams as possible — without reinventing the wheel each time.</p>
<p><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/waldhof.png" alt=""/></p>
<p><strong>What development problems did you face prior to using Titanium?</strong></p>
<p>We faced several problems with the app including memory leaks that we had to chase down, the complexity of plain Objective-C compromising our creativity and lastly the deployment time of updates and hotfixes.</p>
<p><strong>Can you walk me through how your team developed this application?</strong></p>
<p>We sat down with our designer and built a concept for many pages. We then decided on the the most efficient way of implementation. Do we use deep-nested Views, templated Views, etc. We even thought about using UIWebViews.</p>
<p>We wanted a truly dynamic application, so we built a skeleton which got data from the server and outputted it. Then we made that data redundant, making it available offline.</p>
<p>We then started the design of the app. First, we got the navigation bar beautiful, then we placed the logo on top of everything. We split our scrum into each window and feature. It was astonishingly easy from there on &#8211; development from top to bottom.</p>
<p>We even were able to build functions generating a whole window subsystem … something which would be extremely messy and complex in Objective-C. For instance, when we want to display game information, we have a global controller which dynamically checks every parameter before the window is generated: orientation, current page, usage history, etc. This generates each window as dynamically as possible.</p>
<p>The development took 6 months, which boils down to 3 1/2 months if we leave out logistical problems (contact with the team, their ideas and feedback, and of course other projects).</p>
<p><strong>How does Titanium fit into your future development plans?</strong></p>
<p>Through this process we gained a ton of experience using Titanium. To keep our skills sharp, we have a hackathon each month and recently we were able to build an app in just 5 hours. It was a home automation application (the backend was implemented with node.js, a few Raspberry Pi&#8217;s, serial connectors and some hacked-together on-off controllers (for light) and one thermometer sensor).</p>
<p>The development is so easy and straightforward that we can build everything our creativity allows us to do. We go from idea to concept in one or two days, and then to a finished app in one month (depending on complexity — the dynamic nature of the soccer app is waaay more complicated than the home-automation system).</p>
<p><strong>What kind of database, content, or cloud services are you accessing?</strong></p>
<p>For the database we&#8217;re using PHP/MySQL on one server as a data aggregation for news and other static data. For dynamic data (i.e. publish-subscribe messaging system for the live-ticker), it’s determined based on the device (performance, capacity, internet speed, etc.) what type of connection routine is used. We also use a server side parser of the static data and data streams from third-party sources, a content provider for dynamic data like games and we use a plain Node.js / LevelDB configuration for everything which has to be quick and fast.</p>
<p>For the content we’re using a database for in-app data. We built an update distribution system which can update the app without losing our AppStore rating. With Titanium this is easy since we are unable leave the Javascript-sandbox and can’t in any way execute malicious code.</p>
<p>We&#8217;re using Titanium Analytics, Google Analytics and a self-built analytics system. Our own backends and cloud-solutions are backed by Level3, AWS EC2 and Elastic Load Balancing.</p>
<p><strong>What kind of native features are you using in your app?</strong></p>
<p>We’re using the native UI, video (MP4s from YouTube), the camera, a SQL database and geolocation for analytics and cache data using direct file system access with indices stored as JSON.</p>
<hr />
<p>Big thanks to Kenan for taking the time to give us some insight into his experience and success with Titanium app development. Interested in having your Titanium app showcased? Send us an email at community@appcelerator.com and share your story with us!</p>]]></content:encoded>
         <category>@en</category>
      </item>
      <item>
         <title>Building a custom front-end to ACS using Node.ACS [Part 1]</title>
         <link>http://developer.appcelerator.com/blog/2013/05/building-a-custom-front-end-to-acs-using-node-acs-part-1.html</link>
         <description>With Titanium you use Javascript to build native mobile Apps. With Node.ACS you now can use Javascript to write your back-end code, with super easy access to ACS database and storage, all hosted on our secure and scalable cloud infrastructure. As an added advantage, your local Node.ACS installation is a self-contained environment, that doesn&amp;#8217;t require [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21059</guid>
         <pubDate>Fri, 31 May 2013 21:28:42 +0000</pubDate>
         <content:encoded><![CDATA[<style>
.appc_code{
background-color:#000;color:#f2f2f2;padding:5px;margin:5px;}
</style>
<p>With Titanium you use Javascript to build native mobile Apps.  With Node.ACS you now can use Javascript to write your <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2013/05/appcelerator-node-acs-financial-stock-watch-list.html">back-end code</a>, with super easy access to <a rel="nofollow" target="_blank" href="http://www.appcelerator.com/cloud/">ACS database and storage</a>, all hosted on our secure and scalable cloud infrastructure.  As an added advantage, your local Node.ACS installation is a self-contained environment, that doesn&#8217;t require you to install a local web server for testing.  As you will see later on, when you run a Node.ACS app, it is automatically listening for requests on a given HTTP Port; you just have to point your browser to it!</p>
<h2>Getting started</h2>
<p>Assuming you have <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/titanium/latest/#!/guide/Installing_Node">Node and NPM</a>, open up a terminal/command window and type:</p>
<div class="appc_code">
$ sudo npm install -g acs
</div>
<p>This will install Node.ACS globally on your computer.  To start using it you need to login to your appcelerator account by typing:</p>
<div class="appc_code">
$ acs login
</div>
<p>Now that you have successfully logged in, you&#8217;re ready to create your first app.  Change to the folder where you&#8217;d like your app to live, for example <b>cd ~/Documents/MyApps</b> and type:</p>
<div class="appc_code">
$ acs new MyFirstApp
</div>
<p>This command will create for you a new folder with the name of your new app.  Now change to that folder (<b>cd MyFirstApp</b>) and you&#8217;ll see the files that were created for you.  I&#8217;ll explain them later.
<p>To run the app, simply type:</p>
<div class="appc_code">
$ acs run
</div>
<p>Your terminal/command window will show something like this:</p>
<p><center><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/nodeacs0.png"/></center></p>
<p>When you run your app, Node.ACS is actually setting up a local server for you and at this point it is waiting for connections.  As you can see in the screenshot above, ACS is listening on port 8080.  This means that all you need to do is browse to that address.  Launch up your web browser and point it to http://localhost:8080 and you&#8217;ll see this:</p>
<p><center><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/nodeacs1.png"/></center></p>
<p>This HTML page is being served by your local Node.ACS server, but it&#8217;s much more than this.  Node.ACS has a full-featured MVC framework based on <a rel="nofollow" target="_blank" href="http://expressjs.com/">ExpressJS</a>.  If you go to your application folder you&#8217;ll see that some files and folders were created for you.</p>
<p><center><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/nodeacs2.png"/></center></p>
<p>These folders/files are explained in more detail in <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/cloud/latest/#!/guide/node_mvc">this page</a>, so make sure you check it out.  However, I&#8217;ll explain how to work with some of these files from a practical standpoint, and in the process we&#8217;ll create a complete website.</p>
<h2>Building a Website </h2>
<p>If you&#8217;re new to MVC this will probably take some time reading the code, testing and re-reading, but simply because of how MVC separates concerns.  With an MVC framework, your pages(views) are static.  When you want to make them dynamic, you pass static information to them.  A templating engine then takes over to render the static page with new dynamic data.  If you come from a background of developing websites using a &#8220;traditional&#8221; paradigm, MVC may feel weird at first.  If you have worked with other MVC frameworks before, they you will feel right at home.  In any case, MVC is arguably the best way of writing scalable applications.</p>
<p>If you go to your &#8220;Views&#8221; folder, you&#8217;ll see a file named &#8220;index.ejs&#8221;.  Instead of an HTML extension, it is using EJS.  The reason for this is that Node.ACS is using <a rel="nofollow" target="_blank" href="http://embeddedjs.com/">Embedded Javascript</a> as its templating engine.</p>
<div class="appc_code">
<pre>
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
     &lt;title&gt;&lt;%= title %&gt;&lt;/title&gt;
    &lt;link rel='stylesheet' href='/css/style.css' /&gt;
  &lt;/head&gt;
  &lt;body&gt;
       &lt;h2&gt;Node.ACS&lt;/h2&gt;
    &lt;p&gt;&lt;%= title %&gt;&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
</div>
<p>Notice <b>&lt;%= title %&gt;</b> inside the Title Tag and the Body.  This is the way you tell EJS to insert dynamic data into your template.  <b>Title</b> in this case is a variable that was sent to the template before getting it rendered and sent to the browser.  The benefit of using these templates is that you build your HTML as a static page, and use placeholders during your design process to represent dynamic data.  When your page is ready to be implemented, you simply change the dynamic parts to use the corresponding variable name and save the file with .ejs extension.  To show the page with dynamic data, you use the page controller, which you can find under controllers/application.js.</p>
<div class="appc_code">
<pre>
function index(req, res) {
     res.render('index', { title: 'Welcome to Node.ACS!' });
}
</pre>
</div>
<p>This function is receiving two objects: req and res.  As their names imply, req has information about how the user got here (the request), and res holds information and provides methods to take the user some place else (the response).</p>
<p>In this example we&#8217;re using the &#8220;render&#8221; method of the res object.  This method is receiving the name of the view, and an object with all the variables that you&#8217;d like to make available to your view, in this case title, and the static template gets rendered with this new data.  If you change the value of title, you&#8217;ll see it changing on the browser.  However your server is still running with a previous version of your files.  You need to stop the server and restart it because that part of the Javascript function is already running and changes will not take effect until you run it again.  This is as simple as going to your terminal, hitting CTRL+C to break the execution, and running &#8220;acs run&#8221; again; or simply pressing the &#8220;up&#8221; key on your keyboard which will type it for you.</p>
<p>We&#8217;re still missing one important detail.  How do we tell the framework that the &#8220;main&#8221; page of your app will be handled by the <b>index</b> function that lives inside application.js?  You configure these mapping (or route as they&#8217;re called) in config.json.
<div class="appc_code">
<pre>
{
  "routes":
  [
    { "path": "/", "callback": "application#index" }
  ],
  "filters":
  [
        { "path": "/", "callback": "" }
  ],
  "websockets":
  [
       { "event": "", "callback": ""}
  ]
}
</pre>
</div>
<p>In this file we&#8217;re saying that when you browse to the home page, it will execute the function index inside application.js.  We&#8217;ll see more about filters in the second part of this post, and websockets are explained <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/cloud/latest/#!/guide/node_quickstart-section-3">here</a>.</p>
<p>For simplicity, let&#8217;s create a trivial page that will be displayed when navigating to /newpage.</p>
<h3>Step 1:  Create your route by adding it to your config.json</h3>
<div class="appc_code">
<pre>
[
    { "path": "/", "callback": "application#index" },
    { "path": "/newpage", "callback": "newpage#newpage" }
]
</pre>
</div>
<h3>Step 2: Write the &#8220;newpage&#8221; function in newpage.js.  I&#8217;m using a separate file for illustration purposes.</h3>
<div class="appc_code">
<pre>
function newpage(req,res){
     res.render('newpage', { greeting: 'I am the new page' });
}
</pre>
</div>
<h3>Step 3: Create the template called newpage and make sure it is using the new variable &#8220;greeting&#8221;.</h3>
<div class="appc_code">
<pre>
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
     &lt;title&gt;&lt;%= greeting %&gt;&lt;/title&gt;
    &lt;link rel='stylesheet' href='/css/style.css' /&gt;
  &lt;/head&gt;
  &lt;body&gt;
       &lt;h2&gt;Node.ACS&lt;/h2&gt;
    &lt;p&gt;&lt;%= greeting %&gt;&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
</div>
<p>Restart your server and browse to your page.  Then change the URL to http://localhost:8080/newpage and you&#8217;ll see the new page.</p>
<p>These are the basic principles for building websites using Node.ACS.  To learn more about the EJS templating engine and how you can use loops, arrays and other fun Javascript features, go to <a rel="nofollow" target="_blank" href="http://embeddedjs.com/getting_started.html">http://embeddedjs.com/getting_started.html</a>.  To learn more about the &#8220;response&#8221; and &#8220;request&#8221; objects, you can go to <a rel="nofollow" target="_blank" href="http://expressjs.com/api.html#req.params">http://expressjs.com/api.html#req.params</a>.  </p>
<p>If you want to publish your website for everyone to see, simply type</p>
<div class="appc_code">
$ acs publish
</div>
<p>Node.ACS will give you a public URL in return.  The next time you publish, use the &#45;&#45;force parameter to tell Node.ACS to overwrite your previous pages.</p>
<h2>Final thoughts</h2>
<p>This is a full-featured web MVC framework.  You can use anything you&#8217;d normally use when developing websites, such as JQuery or Bootstrap.  Just make sure that any library you use, or any dependency for that matter, is saved in the /public folder.  From your views, the /public folder is the root folder, so if you placed an image at /public/image.png, from your view you would reference it like &lt;img src=&#8221;/image.png&#8221; /&gt;</p>
<p>Stay tuned for the second part of this post, where we&#8217;ll apply this concepts to build a custom front-end to ACS.</p>
<h3>Have fun!</h3>]]></content:encoded>
         <category>@en</category>
      </item>
      <item>
         <title>3.1.1 Release Candidate of Titanium SDK/Studio Now Available</title>
         <link>http://developer.appcelerator.com/blog/2013/05/3-1-1-release-candidate-of-titanium-sdkstudio-now-available.html</link>
         <description>We&amp;#8217;re pleased to announce the release candidate of an update to our 3.1.0 version of Titanium SDK/Studio. Version 3.1.1 brings hundreds of fixes and improvements across both products. Today, we&amp;#8217;re asking you to help test out the release and provide feedback before it becomes generally available in early June. Note: This is a pre-production release, [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21047</guid>
         <pubDate>Fri, 24 May 2013 21:53:12 +0000</pubDate>
         <content:encoded><![CDATA[<p>We&#8217;re pleased to announce the release candidate of an update to our 3.1.0 version of Titanium SDK/Studio. Version 3.1.1 brings hundreds of fixes and improvements across both products. Today, we&#8217;re asking you to help test out the release and provide feedback before it becomes generally available in early June.</p>
<p>Note: This is a pre-production release, and as such may contain regressions or other issues. Please do not use it in production, and keep backups of all important projects and data. <strong>If you find an issue, please report it in <a rel="nofollow" target="_blank" href="http://jira.appcelerator.org">JIRA</a></strong> with a reproducible test case. <strong>We ask you provide feedback by Wednesday, 5/29.</strong></p>
<h3>How to Update</h3>
<p>These are links to continuous integration builds. To install them, choose &#8220;Help Menu &gt; Install Specific Titanium SDK…&#8221; from inside Titanium Studio.</p>
<ul>
<li><a rel="nofollow" target="_blank" href="http://builds.appcelerator.com.s3.amazonaws.com/mobile/3_1_X/mobilesdk-3.1.1.v20130523143543-osx.zip">OSX</a></li>
<li><a rel="nofollow" target="_blank" href="http://builds.appcelerator.com.s3.amazonaws.com/mobile/3_1_X/mobilesdk-3.1.1.v20130523143543-linux.zip">Linux</a></li>
<li><a rel="nofollow" target="_blank" href="http://builds.appcelerator.com.s3.amazonaws.com/mobile/3_1_X/mobilesdk-3.1.1.v20130523143543-win32.zip">Windows</a></li>
</ul>
<p>To update Studio, please visit <a rel="nofollow" target="_blank" href="http://preview.appcelerator.com/">http://preview.appcelerator.com</a> and follow the instructions to update to the RC stream, or to download a new install.</p>
<h3>NPM Packages</h3>
<div><em>Note: You may need to use &#8216;sudo&#8217; before these terminal commands on OSX and Linux</em></div>
<pre>npm install -g <a rel="nofollow" target="_blank" href="mailto:alloy@1.1.3-alpha">alloy@1.1.3-alpha</a>
npm install -g <a rel="nofollow" target="_blank" href="mailto:titanium@3.1.1-alpha">titanium@3.1.1-alpha</a></pre>
<div>To revert back to stable versions:</div>
<pre>npm remove -g titanium
npm install -g titanium
npm remove -g alloy
npm install -g alloy</pre>
<h3>Updates in Titanium 3.1.1</h3>
<p>Read the complete <a rel="nofollow" target="_blank" href="http://docs.appcelerator.com/titanium/release-notes/?version=3.1.1.RC">Release Notes</a>. A full list of updates is available <a rel="nofollow" target="_blank" href="http://jira.appcelerator.org/secure/IssueNavigator.jspa?mode=hide&amp;requestId=15204">here</a>.</p>
<p><strong>Changes in supported OS versions</strong></p>
<p>3.1.1 now has a minimum supported Android version of 2.3.3 (API level 10). The minimum iOS supported version is 5.x, which requires Xcode 4.3 or later.</p>
<p><strong>API Changes</strong></p>
<p>We&#8217;ve updated Titanium.Calendar, and deprecated Titanium.Android.Calendar.</p>
<p><strong>Tooling updates</strong></p>
<p>Support for Android r22 tooling. See <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2013/05/updating-to-android-r22-tools.html">Updating to Android r22 Tools</a> for information about supporting older SDKs. Note that this beta still has some issues with r22 tooling on Windows, but this will be addressed in the final release.</p>
<p><strong>Google Maps Support</strong></p>
<p>We added a new userLocationButton property and updated the regionchanged event.</p>
<p><strong>BlackBerry Support</strong></p>
<p>We&#8217;ve folded in the latest version of our BlackBerry platform to this release. It&#8217;s no longer a separate download.</p>]]></content:encoded>
      </item>
      <item>
         <title>Updating to Android r22 Tools</title>
         <link>http://developer.appcelerator.com/blog/2013/05/updating-to-android-r22-tools.html</link>
         <description>Recently Google released an update (r22) to their Android developer tooling. This update has rearranged the directory structure of the tools and breaks the building of Android projects both from the CLI and inside Titanium Studio. Unless you need the updated functionality we recommend you hold off updating for now. How do I know if [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21038</guid>
         <pubDate>Thu, 23 May 2013 21:06:15 +0000</pubDate>
         <content:encoded><![CDATA[<p>Recently Google released an update (r22) to their Android developer tooling. This update has rearranged the directory structure of the tools and breaks the building of Android projects both from the CLI and inside Titanium Studio. Unless you need the updated functionality we recommend you hold off updating for now.</p>
<h3>How do I know if I&#8217;ve run into this issue?</h3>
<p>See <a rel="nofollow" target="_blank" href="https://jira.appcelerator.org/browse/TIMOB-13944">TIMOB-13944</a>. You&#8217;ll get a failure similar to &#8220;TypeError: argument of type &#8216;NoneType&#8217; is not iterable&#8221;</p>
<h3>How do I fix this problem?</h3>
<p>There are a number of different ways to address the issue, depending on your goals:</p>
<p>If you want to use just the very latest version of the SDK, download the pre-release 3.1.1 build from <a rel="nofollow" target="_blank" href="http://builds.appcelerator.com.s3.amazonaws.com/index.html#3_1_X">http://builds.appcelerator.com.s3.amazonaws.com/index.html#3_1_X</a></p>
<p>If you need  to use prior versions of the SDK:</p>
<ul>
<li>You can create symlinks between the old and new locations of the test tools:
<ul>
<li>ln -s /Applications/Android-sdk/build-tools/17.0.0/aapt aapt ln -s /Applications/Android-sdk/build-tools/17.0.0/dx dx</li>
</ul>
</li>
<li>You can download the previous version of the tools:
<ul>
<li><strong>Linux</strong>: <a rel="nofollow" target="_blank" href="http://dl.google.com/android/android-sdk_r21.1-linux.tgz">http://dl.google.com/android/android-sdk_r21.1-linux.tgz</a></li>
<li><strong>OS X:</strong> <a rel="nofollow" target="_blank" href="http://dl.google.com/android/android-sdk_r21.1-macosx.zip">http://dl.google.com/android/android-sdk_r21.1-macosx.zip</a></li>
<li><strong>Windows:</strong> <a rel="nofollow" target="_blank" href="http://dl.google.com/android/android-sdk_r21.1-windows.zip">http://dl.google.com/android/android-sdk_r21.1-windows.zip</a></li>
</ul>
</li>
</ul>]]></content:encoded>
      </item>
      <item>
         <title>Featured Developer – ArtistBox</title>
         <link>http://developer.appcelerator.com/blog/2013/05/featured-developer-artistbox.html</link>
         <description>Today&amp;#8217;s featured blog post comes from the creators of ArtistBox, Lucica Ibanescu and Titan Dan Tamas. ArtistBox is a sexy Titanium app that provides detailed information, news and music from your favorite artists. Learn more about their experience with Titanium below. We&amp;#8217;d like to share with you our story on how we built ArtistBox and [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=21024</guid>
         <pubDate>Thu, 23 May 2013 20:14:46 +0000</pubDate>
         <content:encoded><![CDATA[<p><em>Today&#8217;s featured blog post comes from the creators of <a rel="nofollow" title="ArtistBox" target="_blank" href="https://itunes.apple.com/us/app/artistbox/id636197114?ls=1&amp;mt=8">ArtistBox</a>, <a rel="nofollow" title="Lucica" target="_blank" href="https://twitter.com/nosoloweb">Lucica Ibanescu</a> and Titan <a rel="nofollow" title="Dan Tamas" target="_blank" href="http://twitter.com/dan_tamas">Dan Tamas</a>. ArtistBox is a sexy Titanium app that provides detailed information, news and music from your favorite artists. Learn more about their experience with Titanium below.</em></p>
<hr />
<p>We&#8217;d like to share with you our story on how we built <a rel="nofollow" title="ArtistBox" target="_blank" href="https://itunes.apple.com/us/app/artistbox/id636197114?ls=1&amp;mt=8">ArtistBox</a> and to give you some insights on how we solved the (not a few) issues that we had.</p>
<p><strong>What&#8217;s ArtistBox?</strong></p>
<p>Artistbox is an iPhone application that finds the most complete information about your favourite artists: their biography, discography, news, concerts in your area and worldwide, videoclips, pictures and similar artists.</p>
<p>We strive to gather way more information than any other music discovery app on the market &#8211; for example by adding up-to-date news or hi-res pictures &#8211; and for the next versions we will add more cool features.</p>
<p><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/artistbox-bg.png" alt=""/></p>
<p><strong>Why Titanium and why not native?</strong></p>
<p>The app has two components: a client side &#8211; the app itself &#8211; and a server side. The whole app was build in five months by just two programmers <a rel="nofollow" title="Dan Tamas" target="_blank" href="http://twitter.com/dan_tamas">@dan_tamas</a> and <a rel="nofollow" title="Nosoloweb" target="_blank" href="https://twitter.com/nosoloweb">@nosoloweb</a> and we feel that coding it in objC wouldn&#8217;t have given us such an advantage from the time point of view.</p>
<p>There are many other reasons we chose Titanium:</p>
<ul>
<li>depending on how the app sells we might want to go cross platform and build an Android version. In this case we will only have to work on the UI side of the app while anything else will remain untouched and working out of the box.</li>
<li>the fact that with a few lines of code we could have a working proof of concept was an amazing advantage over doing mockups and then implementing them in the code.</li>
<li>we are very proficient with Appcelerator but we don&#8217;t know objC so we used what we knew best</li>
<li>we bootstrapped this so the development cost was only in hours of work and not having to pay one or more objC programmers was a real boost.</li>
<li>we developed the server in NodeJS at the same time with the app. Developing both the app and the server side in Javascript instead of JS and objC helped us keep the focus on the building proccess.</li>
</ul>
<p>&nbsp;<br />
&nbsp;</p>
<p><strong>What issues did you need to overcome</strong></p>
<p>At this point we&#8217;d like to get a little more technical and explain how we managed to overcome the problems we had with the app.</p>
<p>One issue was the amount of the XHR calls we had to make. When the app opens it fetches all the artists in the device&#8217;s music library and also basic data for each of them. As you can see in the screenshot the application is very visual, we have a lot of images and each artis will have a lot of information:</p>
<p><img src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/artistbox-activemenu.png"></p>
<p><strong>Way too many XHR calls</strong></p>
<p>Our main goal was to make a very responsive app and due to the amount of server calls we had to find a balance between the information sent from the server and the number of calls. So we decided to go with many calls that return a small amount of information. The overall time the user has to wait might be bigger in this case but the app doesn&#8217;t lock and the feedback received is really fast.</p>
<p>We hit a wall here because the ASIHttpRequest &#8211; the objC library Titanium uses on the native side &#8211; has a limit of 4 concurrent requests. The rest of the requests are put in a queue and executed when the previous calls finish.</p>
<p>What ASI does is perfectly correct, there is no point in overloading the network with too may concurrent requests but in our case the user would have had to wait for ALL the images from the previous windows to load in order to be able to receive the current window information.</p>
<p>We modified the <a rel="nofollow" title="XHR Library" target="_blank" href="https://github.com/raulriera/XHR">XHR</a> library to be able to handle a queue and priorities and we set the images to have the lowest priority while the artist information (JSON data) has the highest priority. At the JS level we limit the simultaneous requests for the images at only 3 so we always have a free slot on the native side for the data &#8211; higher priority requests are passed to ASI immediately.</p>
<p>Of course we take advantage of the caching that XHR does and we have a request to the server only once: the first time a new resources is requested or when the time to live expired. This way after the initial load the number of global requests decreases drastically.</p>
<p><strong>Blocking the UI</strong></p>
<p>The images are diplayed in tableViewRows and if we had put the source of the image directy in the imageView the UI would have locked until the image was loaded.</p>
<p>What we did was create the image **but without** the source property, download the image locally and save it then populate the source with the local file URL. This way the table will scroll normally and the pictures will be loaded one by one giving the user a way better experience.</p>
<p><strong>Youtube clips</strong></p>
<p>We have to display lots of videoclips from Youtube which can be done in two ways:</p>
<ol>
<li>open the clip in mobile Safari or the Youtube app. This meant making the user leave ArtistBox and it was not an acceptable option.</li>
<li>use webviews to load the clip &#8211; not a good approach as we had to keep the memory footprint as low as possible.</li>
</ol>
<p>We came with a different approach: each time the user taps on a clip the app makes a call to the mobile version of the Youtube site, finds the streaming link and opens a videoplayer with the source URL set to this streaming link.</p>
<p>The disadvantage is that the user will have to wait for an extra request to the Youtube servers but the overhead is not too big. The fact that he/she can see the videoclip right inside the app makes it worth it.</p>
<p>There were a few more aspects we had to take care of. The first one was to show very clearly that the videos are coming from Youtube so we designed the thumbnails with the big &#8220;Youtube&#8221; watermark. We also had to filter the results within the Youtube APIs to return only the videos allowed to run on mobile and also in the user&#8217;s country.</p>
<p>You can <a rel="nofollow" title="Titanium YT Player module" target="_blank" href="https://github.com/rborn/TitaniumYoutubePlayer">download the module from Github</a>, it is MIT licensed.</p>
<p>We believe that the complexity of <a rel="nofollow" title="ArtistBox" target="_blank" href="https://itunes.apple.com/us/app/artistbox/id636197114?ls=1&amp;mt=8">ArtistBox</a> pushed the Titanium framework to the limits as we are using a large number of its APIs in our app (tableViews, videoPlayer, audioPlayer, lots of imageViews, scrollableViews, httpClient, localStorage, UI transtions, webviews, etc) and not always in a common way. But we also believe that Titanium was the right choice and it reached our expectations :)</p>
<p>There are also a few modules we used and we want to thank their creators:</p>
<p>- a modified version of <a rel="nofollow" title="XHR" target="_blank" href="https://github.com/raulriera/XHR">XHR</a> by Raul Riera<br />
- <a rel="nofollow" title="TiNetworkHelpers" target="_blank" href="https://github.com/benbahrenburg/TiNetworkHelpers">TiNetworkHelpers</a> by Ben Bahrenburg<br />
- a modified version of <a rel="nofollow" title="Ti Mini Browser" target="_blank" href="https://github.com/Nyvra/TiMiniBrowser">TiMiniBrowser</a> by Rafael Kellermann Streit</p>
<p><strong>Enough talking, let&#8217;s see some action</strong></p>
<p> 
<p><a rel="nofollow" target="_blank" href="http://vimeo.com/64870332">ArtistBoxApp</a> from <a rel="nofollow" target="_blank" href="http://vimeo.com/artistboxapp">ArtistBox App</a> on <a rel="nofollow" target="_blank" href="http://vimeo.com">Vimeo</a>.</p>
<p><a rel="nofollow" target="_blank" href="http://vimeo.com/64870332">ArtistBoxApp</a> from <a rel="nofollow" target="_blank" href="http://vimeo.com/artistboxapp">ArtistBox App</a> on <a rel="nofollow" target="_blank" href="http://vimeo.com">Vimeo</a>.</p>
<p><strong>Final words</strong></p>
<p><a rel="nofollow" title="ArtistBox" target="_blank" href="https://itunes.apple.com/us/app/artistbox/id636197114?ls=1&amp;mt=8">ArtistBox</a> is a very complex application that has to deal with a huge amount of information while also being memory leaks free. Making it stable and very fast were our main purposes because the users are very sensitive when it comes to huge loading times and repeated crashes. Being able to offer them so much info about their favourite artists while displaying the UI in an instant were two very challenging tasks that we hope we completed successfully. You can see we&#8217;re not trying to be modest here, test the app for yourselves and <a rel="nofollow" title="ArtistBox feedback" target="_blank" href="https://twitter.com/artistboxapp">let us know what you think</a>.</p>]]></content:encoded>
         <category>@en</category>
      </item>
      <item>
         <title>Appcelerator Participates in NASA’s International Space Apps Challenge</title>
         <link>http://developer.appcelerator.com/blog/2013/05/appcelerator-participates-in-nasas-international-space-apps-challenge.html</link>
         <description>Last month, NASA hosted the International Space Apps Challenge &amp;#8211; a 48-hour hackathon that invited citizens from around the world to collaborate to create open-source solutions for problems NASA faces both in space and here on Earth. NASA released a list of more than 50 challenges for hackathon teams to tackle, including a wide range [...]</description>
         <guid isPermaLink="false">http://developer.appcelerator.com/blog/?p=20988</guid>
         <pubDate>Thu, 16 May 2013 21:11:55 +0000</pubDate>
         <content:encoded><![CDATA[<p>Last month, NASA hosted the <a rel="nofollow" title="Space Apps Challenge" target="_blank" href="http://spaceappschallenge.org/">International Space Apps Challenge</a> &#8211; a 48-hour hackathon that invited citizens from around the world to collaborate to create open-source solutions for problems NASA faces both in space and here on Earth. NASA released a list of more than 50 challenges for hackathon teams to tackle, including a wide range of topics such as solar flare, star maps, space stations and renewable energy. Teams could sign up to participate virtually from anywhere  in the world.</p>
<p>We are proud that a few teams from the Appcelerator community participated in the International Space Apps Challenge, and we are excited to showcase their work. Great job, everyone!</p>
<hr />
<p><em>by Ketan Majmudar</em></p>
<p><a rel="nofollow" title="Project T-10" target="_blank" href="http://spaceappschallenge.org/project/t-10/">Project: T-10</a> (pronounced “T-Minus Ten”)</p>
<p><strong>Team (Appcelerator community): </strong><br />
Kate Arkless Gray <a rel="nofollow" title="SpaceKate" target="_blank" href="https://twitter.com/SpaceKate">@SpaceKate</a><br />
João Neves <a rel="nofollow" title="jpgneves" target="_blank" href="https://twitter.com/jpgneves">@jpgneves</a><br />
Ketan Majmudar <a rel="nofollow" title="ketan" target="_blank" href="https://twitter.com/ketan">@ketan</a><br />
Dario Lofish <a rel="nofollow" title="dariolofish" target="_blank" href="https://twitter.com/dariolofish">@dariolofish</a></p>
<p><strong>The Challenge</strong>: <a rel="nofollow" title="Spot the Station" target="_blank" href="http://spaceappschallenge.org/challenge/spot-the-station/ ">Spot the Station</a></p>
<p>NASA recently launched the <a rel="nofollow" title="Spot the station" target="_blank" href="http://spotthestation.nasa.gov">Spot the Station website</a>, which allows people to spot the space station and sign up for alerts when it flies overhead. The tasks were to:</p>
<ul>
<li>“Extend the functionality of the Spot the Station site by building an app that allows you to share your sightings with others.”</li>
<li>“Create a visualization with Spot the Station data.”</li>
</ul>
<p><strong>The Solution:</strong></p>
<p></p> 
<p><a rel="nofollow" target="_blank" href="http://vimeo.com/65257119">T-10</a> from <a rel="nofollow" target="_blank" href="http://vimeo.com/user2099078">João Neves</a> on <a rel="nofollow" target="_blank" href="http://vimeo.com">Vimeo</a>.</p>
<p><strong>Overview</strong></p>
<p>Our goal was to set up an alert to help astronauts on the International Space Station (ISS) take images of planet Earth under their specific desired circumstances. For example, they might want a picture of London with clear skies or a picture of New York during a thunderstorm.</p>
<p>The T-10 app allows astronauts to select cities of interest, time of day and the weather condition required. This data is then sent to our server, which waits for the correct conditions and finds the next scheduled times the ISS will be over the city in question. When both city and weather conditions are met, a push notice is sent to the app and provides an alert 10 minutes before the ISS will enter visibility of that city, giving astronauts enough time to prepare to take the photo.</p>
<p><img class="aligncenter" src="http://www.appcelerator.com.s3.amazonaws.com/blog/dev/t-10-blog.jpg" alt=""/></p>
<p>When the T-10 countdown begins, it also sends a push alert to any ground users who have the app installed and would like to send a digital wave back to the ISS and the astronauts aboard. This two-way communication creates a social connection and sense of unity, promoting the knowledge that people on Earth and in space are waving at each other.</p>
<p>In future updates, we hope to add the ability to add the #ISSWave hashtag to share pictures to and from the ISS and Earth. We also intend to add more complex controls to manage when and how alerts get stored and shared with others.</p>
<p><strong>Getting Started</strong></p>
<p>I signed up for the International Space Apps Challenge in London, held at the Google Campus in East London. I had been invited to take part in a European space apps hack recently, but due to working commitments, I completely missed it. When I saw the announcement for the International Space Apps challenge, I signed up as quickly as I could. Being a NASA-driven event just added to the awesomeness of the hackathon. My main goal was just to participate, and I wasn&#8217;t even intending to take part seriously in the challenge aspect. I was more than happy to network and tinker with some cool ideas and people over the weekend.</p>
<p>A very early start on Saturday morning was a challenge in itself, having been up late every night for the past two weeks working on the SCI-FI-LONDON film festival app, but I felt it was my duty to make the effort for this hackathon. To be honest, I didn&#8217;t know what kind of people would be present or if I would have the energy to stick through a whole weekend. I went in expecting to build an app using the Patino game engine for Titanium, as I’m on the private beta &#8211; perhaps a cosmic windchime or mapping related to a comet or near-Earth object. But in the midst of the opening pitches and the multitude of available broad challenges to choose from, fate and social connections led us to form our team and the app T-10.</p>
<p>I tweeted Kate Arkless Gray (<a rel="nofollow" title="SpaceKate" target="_blank" href="https://twitter.com/SpaceKate">@SpaceKate</a>) &#8211; whom I&#8217;d met through Bill Thompson (<a rel="nofollow" title="billt" target="_blank" href="https://twitter.com/billt">@billt</a>), a technology journalist who works for the BBC Click Radio programme &#8211; and we connected with an idea to build an alerting app system which related to current earth weather patterns. Although my original idea was more Earth-bound, Kate had actually asked astronauts from the ISS if they would use an app that would tell them when the weather was good so they could take snaps of the planet! This was a cool plan, and we set it in motion.</p>
<p>Kate&#8217;s friend Joao Neves (<a rel="nofollow" title="jpgneves" target="_blank" href="https://twitter.com/jpgneves">@jpgneves</a>), a software engineer and Android hacker from Stockholm, came on board, and we decided to use Titanium as the core of the application and build a server component. What I most enjoy about the Titanium platform is that it allows me to take the foundation of my learned skill sets and apply it to something amazing that is inclusive within the mobile community. Targeting multiple platforms is awesome, and being JavaScript-based, Titanium has helped me embrace the language in a way I never would have before.</p>
<p><strong>The Process</strong></p>
<p>We had to make sure we had the right APIs on hand and a suitable user-flow. We found a table that would be our home for the next 12 hours and had an open recruitment office in the form of stickies on the edge of our table. We sat and began coding an app that would use ACS push notifications and a bunch of open-source Titanium scripts. We had so much fun building, designing and conceptualising the app and solution that we wanted to weave a few more ideas in, knowing that we could never achieve the Flickr pool upload, share integration and Earth-based &#8220;wave&#8221; functionality that would enable people on the ground to send a virtual wave to the ISS as it flew over.</p>
<p>When our fourth team member, designer Dario Lofish (<a rel="nofollow" title="Dariolofish" target="_blank" href="https://twitter.com/dariolofish">@dariolofish</a>), logged on, our dream team was complete. We all connected online, made sure we were in tune with the concept and approach, then got back to our roles.</p>
<p>As fate would have it, the ISS was due to fly over London at around 9:30, and Kate dragged us (plus about 10 others) so we could see it fly over. Then back to the hacking. Under normal circumstances, we would have stayed all night, but by 22:30, I bailed to the far recesses of North London, promising to return the following morning.</p>
<p>App design during hackathons can be crazy, but we managed to have clear roles and had a simple core concept that we were all behind. Titanium made it easy to prototype ideas and integrate design ideas on the fly quickly.</p>
<p><strong>Highlights &amp; Insights</strong></p>
<p>Our demo at the end of the day went really well, and I demonstrated the functionality of setting and sending the event from my iPhone 4S plugged directly into the projector, with push notification responses. It was a real joy to be part of the team behind T-10, and I&#8217;m proud of the ease and speed with which our team locked into the development process and how easy we made all of our jobs seem.</p>
<p>I was pleased to see a lot of mobile solutions come out of the weekend, many of them trying to take complex space data and put them into the hands of ordinary people in a way that makes sense. There were some superb, inspiring solutions that bridged the gap between software and hardware. It was also incredible to see the cooperation and coordination of people, some in the same room, some located all over the world. Since I was 10, I have had this odd dream to become a developer &#8211; back then it was just a desire to be a computer programmer. Mobile development has suddenly become a huge business and one that has moved in from the fringe of society into an evolving and ever-shifting set of features and parameters. With every year, new concepts, gestures and devices evolve and play a role in how our societies interact with the world around us. It is very cool and exciting to be part of that change.</p>
<p>At the end of the hackathon, we were so excited when they announced that we had been chosen by the judges as one of the two winning London Challenge teams! We are hoping that we will do well in the global round coming up and that our app will be featured in the Victoria and Albert Museum as part of the Digital Futures: <a rel="nofollow" title="Urban Open Street Event" target="_blank" href="http://www.vam.ac.uk/whatson/event/2481/digital-futures-urban-open-space-3776/">Urban Open Space event</a>.</p>
<p>We are now in the People&#8217;s Choice voting phase, so you can vote for <a rel="nofollow" title="Project voting" target="_blank" href="http://spaceappschallenge.org/project/t-10/">T-10 via Twitter</a>. Wish us luck!</p>]]></content:encoded>
         <category>@en</category>
      </item>
      <item>
         <title>Volando voy! volando vengo!</title>
         <link>http://pec1985.com/pv/volando-voy-volando-vengo/</link>
         <guid isPermaLink="false">http://pec1985.com/?p=176</guid>
         <pubDate>Sat, 04 May 2013 17:52:41 +0000</pubDate>
         <content:encoded><![CDATA[<p><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_002.jpg" alt="Pedro_20130427_002" width="900" height="506" class="alignnone size-full wp-image-178"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_004.jpg" alt="Pedro_20130427_004" width="900" height="506" class="alignnone size-full wp-image-179"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_006.jpg" alt="Pedro_20130427_006" width="900" height="506" class="alignnone size-full wp-image-180"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_009.jpg" alt="Pedro_20130427_009" width="900" height="506" class="alignnone size-full wp-image-181"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_010.jpg" alt="Pedro_20130427_010" width="900" height="506" class="alignnone size-full wp-image-182"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_012.jpg" alt="Pedro_20130427_012" width="900" height="506" class="alignnone size-full wp-image-183"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_013.jpg" alt="Pedro_20130427_013" width="900" height="506" class="alignnone size-full wp-image-184"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_014.jpg" alt="Pedro_20130427_014" width="900" height="506" class="alignnone size-full wp-image-185"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_015.jpg" alt="Pedro_20130427_015" width="900" height="506" class="alignnone size-full wp-image-186"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_016.jpg" alt="Pedro_20130427_016" width="900" height="506" class="alignnone size-full wp-image-187"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_017.jpg" alt="Pedro_20130427_017" width="900" height="506" class="alignnone size-full wp-image-188"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_018.jpg" alt="Pedro_20130427_018" width="900" height="506" class="alignnone size-full wp-image-189"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_019.jpg" alt="Pedro_20130427_019" width="900" height="506" class="alignnone size-full wp-image-190"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_020.jpg" alt="Pedro_20130427_020" width="900" height="506" class="alignnone size-full wp-image-191"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_021.jpg" alt="Pedro_20130427_021" width="900" height="506" class="alignnone size-full wp-image-192"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_022.jpg" alt="Pedro_20130427_022" width="900" height="506" class="alignnone size-full wp-image-193"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_028.jpg" alt="Pedro_20130427_028" width="900" height="506" class="alignnone size-full wp-image-194"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_029.jpg" alt="Pedro_20130427_029" width="900" height="506" class="alignnone size-full wp-image-195"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_031.jpg" alt="Pedro_20130427_031" width="900" height="506" class="alignnone size-full wp-image-196"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_032.jpg" alt="Pedro_20130427_032" width="900" height="506" class="alignnone size-full wp-image-197"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_033.jpg" alt="Pedro_20130427_033" width="900" height="506" class="alignnone size-full wp-image-198"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_035.jpg" alt="Pedro_20130427_035" width="900" height="506" class="alignnone size-full wp-image-200"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/05/Pedro_20130427_042.jpg" alt="Pedro_20130427_042" width="900" height="506" class="alignnone size-large wp-image-202"/></p>]]></content:encoded>
         <category>private</category>
      </item>
      <item>
         <title>Fotos chulas</title>
         <link>http://pec1985.com/pv/fotos-chulas/</link>
         <guid isPermaLink="false">http://pec1985.com/?p=161</guid>
         <pubDate>Tue, 16 Apr 2013 04:32:40 +0000</pubDate>
         <content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-173" alt="Pedro_20130311_002" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130311_002.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-172" alt="Pedro_20130316_005" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130316_005.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-171" alt="Pedro_20130316_009" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130316_009.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-170" alt="IMG_1462" src="http://pec1985.com/wp-content/uploads/2013/04/IMG_1462.jpg" width="900" height="675"/><br />
<img class="alignnone size-full wp-image-169" alt="IMG_1463" src="http://pec1985.com/wp-content/uploads/2013/04/IMG_1463.jpg"/><br />
<img class="alignnone size-full wp-image-167" alt="IMG_1478" src="http://pec1985.com/wp-content/uploads/2013/04/IMG_1478.jpg" width="900" height="675"/><br />
<img class="alignnone size-full wp-image-166" alt="IMG_1499" src="http://pec1985.com/wp-content/uploads/2013/04/IMG_1499.jpg" width="900" height="675"/><br />
<img class="alignnone size-full wp-image-165" alt="Pedro_20130323_002" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130323_002.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-164" alt="Pedro_20130324_007" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130324_007.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-163" alt="Pedro_20130329_006" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130329_006.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-162" alt="Pedro_20130414_018" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_018.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-154" alt="Pedro_20130414_031" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_031.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-148" alt="Pedro_20130414_025" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_025.jpg" width="900" height="506"/></p>]]></content:encoded>
         <category>private</category>
      </item>
      <item>
         <title>Sesión de fotos – Golden Gate</title>
         <link>http://pec1985.com/pv/sesion-de-fotos-golden-gate/</link>
         <guid isPermaLink="false">http://pec1985.com/?p=144</guid>
         <pubDate>Mon, 15 Apr 2013 15:32:56 +0000</pubDate>
         <content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-145" alt="Pedro_20130414_022" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_022.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-146" alt="Pedro_20130414_023" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_023.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-147" alt="Pedro_20130414_024" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_024.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-148" alt="Pedro_20130414_025" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_025.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-149" alt="Pedro_20130414_026" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_026.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-151" alt="Pedro_20130414_028" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_028.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-152" alt="Pedro_20130414_029" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_029.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-153" alt="Pedro_20130414_030" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_030.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-154" alt="Pedro_20130414_031" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_031.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-155" alt="Pedro_20130414_032" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_032.jpg" width="900" height="506"/></p>
<p><img class="alignnone size-full wp-image-156" alt="Pedro_20130414_033" src="http://pec1985.com/wp-content/uploads/2013/04/Pedro_20130414_033.jpg" width="900" height="506"/></p>]]></content:encoded>
         <category>private</category>
      </item>
      <item>
         <title>Cross-platform Nav controller for Titanium</title>
         <link>http://pec1985.com/ti-coding/cross-platform-navigation-controller-to-titanium/</link>
         <description>This is a simple cross-platform navigation controller. Works on Android and iPhone. app.js navigation.js</description>
         <guid isPermaLink="false">http://pec1985.com/?p=139</guid>
         <pubDate>Mon, 25 Mar 2013 23:09:25 +0000</pubDate>
         <content:encoded><![CDATA[<p>This is a simple cross-platform navigation controller. Works on Android and iPhone.</p>
<h3>app.js</h3>
<noscript><pre><code class="language-javascript javascript">var Navigation = require('navigation');

var rootWindow = Ti.UI.createWindow({
  backgroundColor: 'green'
});

var btn = Ti.UI.createButton({
	title: 'next'
});

rootWindow.add(btn);

Navigation.setRootWindow(rootWindow);
Navigation.open();

btn.addEventListener('click', function(){
	var nextWindow = Ti.UI.createWindow({
		title: 'next window',
		backgroundColor: 'red'
	});
	Navigation.open(nextWindow);
});

</code></pre></noscript>
<h3>navigation.js</h3>
<noscript><pre><code class="language-javascript javascript">/**
 * Define constants
 * iPhone and Android
 * @type {BOOL}
 */
const Android = Ti.Platform.osname == 'android';
const iPhone = Ti.Platform.osname == 'iphone';

/**
 * Android and iPhone
 * Navigation Controller
 */
function Navigation(){
	// ignore all this if we're on Android
	this.nav		= iPhone ? Ti.UI.iPhone.createNavigationGroup() : null;
	this._wrapperWinow	= iPhone ? Ti.UI.createWindow() : null;
	this._rootWindow	= null;
	if(iPhone){
		this._wrapperWinow.add(this.nav);
	}
}

/**
 * Opens the navigation group or the window passed
 * @param  {Ti.UI.Window}	_window Window to be opened
 * @param  {Object}			_args   Arguments passed in the open() method
 */
Navigation.prototype.open = function(_window, _args){
	// if no window is passed
	if(!_window){
		if(iPhone){
			// open the navigation group if iPhone
			this._wrapperWinow.open();
		}
		if(Android){
			// open the root window if Android
			this._rootWindow.open();
		}
		return;
	}
	// If a window is passed
	_args = _args || {};
	if(iPhone){
		// open it in the navigation stack
		this.nav.open(_window,_args);
	}
	if(Android){
		// open the window as a heavyweight
		_args.fullscreen = _window.fullscreen || false;
		_window.open(_args);
	}
}

/**
 * Either closes the navigation group or the window passed
 * @param  {Ti.UI.Window} _window Window to be closed (optional)
 */
Navigation.prototype.close = function(_window){
	// if no window is passed
	if(!_window){
		if(iPhone){
			// close the navigation group if iPhone
			this._wrapperWinow.close();
		}
		if(Android){
			// close the root window if Android
			this._rootWindow.close();
		}
		return;
	}
	// If a window is passed
	if(iPhone){
		// close it in the navigation stack
		this.nav.close(_window);
	}
	if(Android){
		// just close the window
		_window.close();
	}
}

/**
 * Sets the root window
 * @param {Ti.UI.Window} _window Window to be set as the root
 */
Navigation.prototype.setRootWindow = function(_window){
	// Sets the root window of the navigatin
	if(iPhone){
		this.nav.setWindow(_window);
	}
	// make the window heavyweight if android
	if(Android){
		_window.fullscreen = _window.fullscreen || false;
	}

	this._rootWindow = _window;

}
module.exports = new Navigation();</code></pre></noscript>]]></content:encoded>
         <category>Ti Coding</category>
      </item>
      <item>
         <title>avoiding memory leaks in titanium</title>
         <link>http://pec1985.com/ti-coding/avoiding-memory-leaks-in-titanium/</link>
         <description>Here we have an example on how to avoid memory leaks. One of the biggest enemies that we have is the global event listener. In order to avoid a leak, we must remove the event from the global Ti.App object. Let&amp;#8217;s take a look: Bad &amp;#8211; Memory leak in line 55 Good &amp;#8211; Memory leak [...]</description>
         <guid isPermaLink="false">http://pec1985.com/?p=70</guid>
         <pubDate>Wed, 20 Mar 2013 22:18:48 +0000</pubDate>
         <content:encoded><![CDATA[<p>Here we have an example on how to avoid memory leaks. One of the biggest enemies that we have is the global event listener. In order to avoid a leak, we must remove the event from the global Ti.App object. Let&#8217;s take a look:</p>
<h3>Bad &#8211; Memory leak in line 55</h3>
<noscript><pre><code class="language-javascript javascript">function Window1() {
	var win = Ti.UI.createWindow({
		fullscreen: false,
		backgroundColor: '#ccc'
	});
	
	var btn = Ti.UI.createButton({
		title: 'open next',
		top: 50,
		width: Ti.UI.SIZE,
		height: Ti.UI.SIZE
	});
 	win.add(btn);
	var num = 0;
	btn.addEventListener('click', function(){
		num++;
		var w = Window2(num);
		w.open();
	});

	return win;
}

function Window2(num) {
	
	var win = Ti.UI.createWindow({
		fullscreen: false,
		backgroundColor: '#ccc',
		title: 'Window: #' + num
	});
	
	var label = Ti.UI.createLabel({
		top:10,
		width: 200,
		height: 50,
		backgroundColor: 'white',
		color: 'black',
		text: ''
	});
	
	var btn = Ti.UI.createButton({
		width: Ti.UI.SIZE,
		height: Ti.UI.SIZE,
		title: 'fire event'
	});
	
	win.add(label);
	win.add(btn);
	
	btn.addEventListener('click', function(){
		Ti.App.fireEvent('change_label', {text: 'event fired'});
	});

	// Memory leak		
	Ti.App.addEventListener('change_label', function(e){
		label.text = e.text;
		Ti.API.info('-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-');
		Ti.API.info('-=-=-=-=-EVENT FIRED-=-=-=-=-=-');
		
	});

	return win;
}

Window1().open();</code></pre></noscript>
<h3>Good &#8211; Memory leak avoided in line 65</h3>
<noscript><pre><code class="language-javascript javascript">function Window1() {
	var win = Ti.UI.createWindow({
		fullscreen: false,
		backgroundColor: '#ccc'
	});
	
	var btn = Ti.UI.createButton({
		title: 'open next',
		top: 50,
		width: Ti.UI.SIZE,
		height: Ti.UI.SIZE
	});
 	win.add(btn);
	var num = 0;
	btn.addEventListener('click', function(){
		num++;
		var w = Window2(num);
		w.open();
	});

	return win;
}

function Window2(num) {
	
	var win = Ti.UI.createWindow({
		fullscreen: false,
		backgroundColor: '#ccc',
		title: 'Window: #' + num
	});
	
	var label = Ti.UI.createLabel({
		top:10,
		width: 200,
		height: 50,
		backgroundColor: 'white',
		color: 'black',
		text: ''
	});
	
	var btn = Ti.UI.createButton({
		width: Ti.UI.SIZE,
		height: Ti.UI.SIZE,
		title: 'fire event'
	});
	
	win.add(label);
	win.add(btn);
	
	btn.addEventListener('click', function(){
		Ti.App.fireEvent('change_label', {text: 'event fired'});
	});
	
	function changeLabel(e) {
		label.text = e.text;
		Ti.API.info('-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-');
		Ti.API.info('-=-=-=-=-EVENT FIRED-=-=-=-=-=-');
	}
	
	// No memory leak
	Ti.App.addEventListener('change_label', changeLabel);

	win.addEventListener('close', function(){
		// Remove the event on window close
		Ti.App.removeEventListener('change_label', changeLabel);
	});

	return win;
}

Window1().open();</code></pre></noscript>]]></content:encoded>
         <category>Ti Coding</category>
      </item>
      <item>
         <title>Create a simple image gallery in titanium</title>
         <link>http://pec1985.com/ti-coding/create-a-simple-image-gallery-in-titanium/</link>
         <description>First, we need to create the image that will be zoomable, to make this easier, we create a function that will give us that automatically: zoomable.js To use this, now we need to create our gallery, this is the commonJS module that will be dropped into our code to show the gallery: gallery.js And finally, [...]</description>
         <guid isPermaLink="false">http://pec1985.com/?p=47</guid>
         <pubDate>Wed, 20 Mar 2013 17:30:02 +0000</pubDate>
         <content:encoded><![CDATA[<p>First, we need to create the image that will be zoomable, to make this easier, we create a function that will give us that automatically:</p>
<h3>zoomable.js
<p><noscript><pre><code class="language-javascript javascript">function Zoomable(image) {
    var scroll = Ti.UI.createScrollView({
        width: Ti.UI.FILL,
        height: Ti.UI.FILL,
        contentWidth: 'auto',
        contentHeight: 'auto',
        
    });
    var image = Ti.UI.createImageView({
        image: image,
        width: Ti.UI.SIZE,
        height: Ti.UI.SIZE
    });
    
    function onLoad() {
        image.removeEventListener('load', onLoad);
        
        var ratio = 0,
            width = image.rect.width,
            height = image.rect.height;
            
        if(width &gt; height) {
            ratio = scroll.rect.width / width;
        } else {
            ratio = scroll.rect.height / height
        }
        scroll.minZoomScale = ratio;
        scroll.zoomScale = ratio;
        image.image = image.image;
    }
    image.addEventListener('load', onLoad);
    scroll.add(image);
    return {
        view: scroll,
        image: image
    }
}
</code></pre></noscript><br />
To use this, now we need to create our gallery, this is the commonJS module that will be dropped into our code to show the gallery:</p>
<h3>gallery.js
<p><noscript><pre><code class="language-javascript javascript">function Gallery(images, startAt) {
    images = images || [];
    startAt = startAt || 0;
    var views = [];
    var imgs = [];
    
    for(var i = 0, len = images.length; i &lt; len; i++) {
        var zoomable = Zoomable(images[i]);
        views.push(zoomable.view);
        imgs.push(zoomable.image);
    }
    
    var scrollable = Ti.UI.createScrollableView({
        views: views,
        currentPage: startAt
    });
    
    return {
        view: scrollable
    }
}
</code></pre></noscript><br />
And finally, an example on how to use it:</p>
<h3>app.js
<noscript><pre><code class="language-javascript javascript">var win = Ti.UI.createWindow();
var images = [];

for(var i = 1; i &lt; 100; i++){
   // Assuming all the images are called image1.jpg, image2.jpeg, etc...
   images.push('/images/image'+i+'.jpg');
    
}
var gallery = Gallery(images,0);

win.add(gallery.view);

win.open();
</code></pre></noscript></h3></h3></h3>]]></content:encoded>
         <category>Ti Coding</category>
      </item>
      <item>
         <title>Login utility for Titanium</title>
         <link>http://pec1985.com/ti-coding/login-utility-for-titanium/</link>
         <guid isPermaLink="false">http://pec1985.com/?p=31</guid>
         <pubDate>Wed, 20 Mar 2013 16:03:26 +0000</pubDate>
         <content:encoded><![CDATA[<noscript><pre><code class="language-javascript javascript">/** 
 * To be used this way
 */

var Log = require('log');

Log.Info('This is an info log');
Log.Error('This is an error log');
Log.Debug('This is a debug log');

// ... more code ...

Log.emailLogFile({
    developer: 'dev@example.com',
    message: 'Something intelligent',
    subject: 'Here is the log'
});</code></pre><pre><code class="language-javascript javascript">var DEBUG = true;
var WRITES = true;

function logFile() {
	return Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory,'titanium_log.txt');
}
 
function logMsg(type, str) {
	if (typeof str == 'object') {
		try {
			str = JSON.parse(str);
		} catch(e) {
			str = JSON.stringify(str);
		}
	}
	return '['+type+' ' + new Date().getTime() + '] ' + str;
}
 
exports.Info = function(str) {
    if(DEBUG){
        if(WRITES)
            logFile().write(logMsg('INFO', str), true);
        Ti.API.info(str);
    }
};
 
exports.Debug = function(str) {
    if(DEBUG){
        if(WRITES)
            logFile().write(logMsg('DEBUG', str), true);
        Ti.API.debug(str);
    }
};
 
exports.Error = function(str) {
    if(DEBUG){
        if(WRITES)
            logFile().write(logMsg('ERROR', str), true);
        Ti.API.error(str);
    }
};
 
/**
 * Gets the actual log file
 */
exports.getLogFile = function() {
    return logFile();
};
 
/**
 * Gets the log file path
 */
exports.getLogFile = function() {
    return logFile().nativePath;
};
 
/**
 * Returns the text of the log file
 */
exports.getLogText = function() {
    return logFile().read();
};
 
/**
 * Opens an email dialog to send the log to the developer
 * @param {Object} params {
 *                  @param developer    Email to be sent to
 *                  @param message      Message to send
 *                  @param subject      Subject in the message
 *                }
 */
exports.emailLogFile = function(params) {
    var developer = params.developer || '';
    var message = params.message || 'Please see attached';
    var subject = params.subject || 'Log file from app';
    
    var email = Ti.UI.createEmailDialog({
        subject: 'Log file from app',
        messageBody: 'Please see attached',
        toRecipients: [developer]
    });
    email.addAttachment(logFile());
};
 
exports.deleteLog = function() {
	logFile().deleteFile();
};

exports.setDebug = function(_bool) {
	DEBUG = _bool;
};

exports.setWritesToFile = function(_bool) {
    WRITES = _bool;
}
</code></pre></noscript>]]></content:encoded>
         <category>Ti Coding</category>
      </item>
      <item>
         <title>beautiful day to fly</title>
         <link>http://pec1985.com/hang-gliding/beautiful-day-to-fly/</link>
         <description>Great day to fly at Trest Pinos, CA. About 1,200 feet off the ground and a couple of light thermos. The cows were friendly :) but they left shit everywhere&amp;#8230; yep! Pictures taken with my Nokia Lumia 920 running Windows 8 Phone!</description>
         <guid isPermaLink="false">http://pec1985.com/?p=10</guid>
         <pubDate>Wed, 20 Mar 2013 02:11:21 +0000</pubDate>
         <content:encoded><![CDATA[<p><br />
Great day to fly at Trest Pinos, CA. About 1,200 feet off the ground and a couple of light thermos.<br />
The cows were friendly :) but they left shit everywhere&#8230; yep!<br />
<img class="alignnone size-full wp-image-103" alt="Pedro_20130309_001" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_001.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-104" alt="Pedro_20130309_002" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_002.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-105" alt="Pedro_20130309_003" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_003.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-106" alt="Pedro_20130309_004" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_004.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-107" alt="Pedro_20130309_005" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_005.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-108" alt="Pedro_20130309_006" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_006.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-109" alt="Pedro_20130309_007" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_007.jpg" width="900" height="506"/><br />
<img class="alignnone size-full wp-image-110" alt="Pedro_20130309_008" src="http://pec1985.com/wp-content/uploads/2013/03/Pedro_20130309_008.jpg" width="900" height="506"/><br />
Pictures taken with my Nokia Lumia 920 running Windows 8 Phone!</p>]]></content:encoded>
         <category>Hang Gliding</category>
      </item>
      <item>
         <title>Practicing on the hill</title>
         <link>http://pec1985.com/hang-gliding/64/</link>
         <description>Very early in my flying training, I had to practice at the hill. Fly straight and land on my feet. Some pictures from those days&amp;#8230;</description>
         <guid isPermaLink="false">http://pec1985.com/?p=64</guid>
         <pubDate>Sun, 24 Jun 2012 19:05:18 +0000</pubDate>
         <content:encoded><![CDATA[<p><br />
Very early in my flying training, I had to practice at the hill. Fly straight and land on my feet. Some pictures from those days&#8230;<br />
<br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1472.jpg" alt="IMG_1472" class="alignnone size-full wp-image-121"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1473.jpg" alt="IMG_1473" class="alignnone size-large wp-image-122"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1474.jpg" alt="IMG_1474" class="alignnone size-large wp-image-123"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1476.jpg" alt="IMG_1476" class="alignnone size-large wp-image-125"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1477.jpg" alt="IMG_1477" class="alignnone size-large wp-image-127"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1478.jpg" alt="IMG_1478" class="alignnone size-large wp-image-128"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1480.jpg" alt="IMG_1480" class="alignnone size-large wp-image-130"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1481.jpg" alt="IMG_1481" class="alignnone size-large wp-image-131"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1482.jpg" alt="IMG_1482" class="alignnone size-large wp-image-132"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1483.jpg" alt="IMG_1483" class="alignnone size-large wp-image-133"/><br />
<img src="http://pec1985.com/wp-content/uploads/2013/03/IMG_1484.jpg" alt="IMG_1484" class="alignnone size-large wp-image-134"/></p>]]></content:encoded>
         <category>Hang Gliding</category>
      </item>
      <item>
         <title>On the phone with someone who gave my app a bad rating</title>
         <link>http://savagelook.com/blog/uncategorized/on-the-phone-with-someone-who-gave-my-app-a-bad-rating</link>
         <description>Sometimes you need a more direct approach&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/uncategorized/on-the-phone-with-someone-who-gave-my-app-a-bad-rating&quot;&gt;On the phone with someone who gave my app a bad rating&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3538</guid>
         <pubDate>Tue, 15 May 2012 13:27:01 +0000</pubDate>
         <content:encoded><![CDATA[<p>Just replace <b>&#8220;let my daughter go now&#8221;</b> with <b>&#8220;re-rate my app&#8221;</b>.</p>
<p></p> 
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/uncategorized/on-the-phone-with-someone-who-gave-my-app-a-bad-rating">On the phone with someone who gave my app a bad rating</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3538"></div>]]></content:encoded>
      </item>
      <item>
         <title>The Joys of Screen Scraping</title>
         <link>http://savagelook.com/blog/android/the-joys-of-screen-scraping</link>
         <description>Knucklehead was down for a bit, but it's up and running again&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/android/the-joys-of-screen-scraping&quot;&gt;The Joys of Screen Scraping&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3495</guid>
         <pubDate>Thu, 01 Mar 2012 20:14:16 +0000</pubDate>
         <content:encoded><![CDATA[<h2>Knucklehead Up and Running Again</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<p><span style="float:left;padding-right:20px;"><a rel="nofollow" target="_blank" href="https://market.android.com/details?id=com.savagelook.knucklehead"><img src="http://savagelook.com/blog/wp-content/uploads/2012/03/kh.png" alt="" title="kh" width="124" height="124" class="alignnone size-full wp-image-3496"/></a></span><br />
For about a week there my MMA fighter app for Android, <a rel="nofollow" target="_blank" href="https://market.android.com/details?id=com.savagelook.knucklehead">Knucklehead</a>, has been out of commission. The reason is that the site that I scrape for data, <a rel="nofollow" target="_blank" href="http://sherdog.com">Sherdog</a> was completely redesigned. I needed to rework a lot of my PHP-based screen scraping code to make it work. My PHP is rusty, but fortunately, my regular expression chops are always sharp. In any case, it&#8217;s back to working order now. </p>
<p>Maybe with a little luck I can get people to re-rate those 1-star ratings I got while it was down. If not, perhaps I can guilt people into giving me good ratings by saying that it&#8217;s my newborn son&#8217;s fault I didn&#8217;t get to it sooner. I mean, really, are you going to give the father of this child a hard time? Don&#8217;t be so heartless. <img src='http://savagelook.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley'/> </p>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/wp-content/uploads/2012/03/charlie.png"><img src="http://savagelook.com/blog/wp-content/uploads/2012/03/charlie.png" alt="" title="charlie" width="600" height="400" class="alignnone size-full wp-image-3507"/></a></p>
<h2 style="padding-top:20px;">Screen Scraping Tips</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<p>As we all know, screen scraping is pretty much the most <span style="color:#a00;">volatile</span> way to supply your apps with data. While no amount of planning can permanently future-proof your screen scraper, there&#8217;s some things you can do to make it easier.</p>
<ul style="padding-bottom:20px;">
<li><strong>Define a data model for what you are scraping</strong>. What made my project relatively easy to get working again was that I had a clearly defined data model shared by both the backend and frontend. In my case, this is a LAMP stack and distributed Android app respectively. Now my users don&#8217;t need to download a new version of my app in order to get the fix. It just works now.</li>
<li><strong>Code the scraper on a backend proxy</strong>, not in the app itself. That way, when your scraper inevitably gets broken at some point (after a year in my case), you only need to change the code in one place. This goes hand-in-hand with defining a data model.</li>
<li><strong>Keep it simple stupid</strong>. Don&#8217;t over-architect a screen scraper. Most data processing code will change over time, but a screen scraper may need a total rewrite at some point. Put all your software engineering skills into controlling what leaves the scraper, but play it pretty loose with what the scraper is going to be processing.</li>
<li><strong>Using JSON? You better be using <a rel="nofollow" target="_blank" href="http://jsonlint.com">jsonlint.com</a> too</strong>. jsonlint.com can save you a lot of time and aggravation when it comes to creating and processing your scraped data. Not only does it validate your JSON, but it will also pretty print it so it&#8217;s easy to read through yourself.</li>
</ul>
<p>That&#8217;s just a couple things that made fixing my scraper a lot less painful. You guys out there have any tips? I&#8217;d love to hear them. All things being equal, I hope I never have to screen scrape for data ever again. But since that&#8217;s pretty unlikely, it&#8217;s good to be prepared for the inevitable obstacles that scraping will present.</p>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/android/the-joys-of-screen-scraping">The Joys of Screen Scraping</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3495"></div>]]></content:encoded>
      </item>
      <item>
         <title>Path menu with Appcelerator Titanium</title>
         <link>http://savagelook.com/blog/portfolio/path-menu-with-appcelerator-titanium</link>
         <description>The talked-about Path menu, implemented in Titanium, for iOS and Android&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/path-menu-with-appcelerator-titanium&quot;&gt;Path menu with Appcelerator Titanium&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3486</guid>
         <pubDate>Thu, 16 Feb 2012 01:57:45 +0000</pubDate>
         <content:encoded><![CDATA[<h2>Here we go again&#8230;</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<p>Yep, another cross-post from the Appcelerator blog. This time it shows off how I managed to implement the dynamic and unique <a rel="nofollow" target="_blank" href="https://path.com">Path</a> menu in Titanium. From a single code base the menu is fully functional, with native performance, on both Android and iOS. </p>
<ul style="padding-bottom:20px;">
<li><a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2012/02/forging-titanium-episode-22-path-like-menu.html">Original blog post</a></li>
<li><a rel="nofollow" target="_blank" href="https://github.com/appcelerator-developer-relations/Forging-Titanium/tree/master/ep-022">Full source code on Github</a></li>
</ul>
<h2>Video</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<p></p> 
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/path-menu-with-appcelerator-titanium">Path menu with Appcelerator Titanium</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3486"></div>]]></content:encoded>
      </item>
      <item>
         <title>BADCamp iOS and Android apps</title>
         <link>http://sumitk.net/portfolio/badcamp-ios-and-android-apps</link>
         <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;p&gt;BadCamp conference app was developed using open source Titanium framework and fetches data from Drupal based Conference Organizing Distribution (COD &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://drupal.org/project/cod&quot;&gt;http://drupal.org/project/cod&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;	App feature includes:&lt;br /&gt;
	- Browse sessions&lt;br /&gt;
	- Browse Speakers&lt;br /&gt;
	- Find conference tweets&lt;br /&gt;
	- Push notifications&lt;br /&gt;
	- Notifications for personal schedule&lt;br /&gt;
	- Automatic updates from live site&lt;br /&gt;
	- Same codebase for iOS and Android&lt;br /&gt;
	- Custom design and fonts on native apps&lt;/p&gt;
&lt;p&gt;	Links:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://itunes.apple.com/us/app/badcamp-2011/id470519171&quot;&gt;http://itunes.apple.com/us/app/badcamp-2011/id470519171&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://market.android.com/details?id=net.sumitk.badcamp2011&quot;&gt;https://market.android.com/details?id=net.sumitk.badcamp2011&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-small field-type-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Small Description:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;BADCamp iOS and Android apps&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-image field-type-image field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Image:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;img src=&quot;http://sumitk.net/sites/default/files/styles/blog_item_fullnode/public/Default_0.png&quot; width=&quot;320&quot; height=&quot;480&quot; alt=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-show-home field-type-list-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Show in Home Page slide:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;Yes&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">6 at http://sumitk.net</guid>
         <pubDate>Tue, 03 Jan 2012 01:24:18 +0000</pubDate>
      </item>
      <item>
         <title>InterAction Conference App</title>
         <link>http://sumitk.net/portfolio/interaction-conference-app</link>
         <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;p&gt;InterAction conference apps - iOS and Android&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-small field-type-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Small Description:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;InterAction conference apps - iOS and Android&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-image field-type-image field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Image:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;img src=&quot;http://sumitk.net/sites/default/files/styles/blog_item_fullnode/public/default_1.png&quot; width=&quot;480&quot; height=&quot;800&quot; alt=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-show-home field-type-list-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Show in Home Page slide:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;Yes&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">5 at http://sumitk.net</guid>
         <pubDate>Tue, 03 Jan 2012 01:18:35 +0000</pubDate>
      </item>
      <item>
         <title>Tumorpedia iOS and Android Apps</title>
         <link>http://sumitk.net/portfolio/tumorpedia-ios-and-android-apps</link>
         <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;p&gt;Tumorpedia iOS and Android Apps&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-small field-type-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Small Description:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;Tumorpedia iOS and Android Apps&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-image field-type-image field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Image:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;img src=&quot;http://sumitk.net/sites/default/files/styles/blog_item_fullnode/public/default_2.png&quot; width=&quot;320&quot; height=&quot;480&quot; alt=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-show-home field-type-list-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Show in Home Page slide:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;Yes&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">4 at http://sumitk.net</guid>
         <pubDate>Tue, 03 Jan 2012 01:17:53 +0000</pubDate>
      </item>
      <item>
         <title>TotalWOD Web, iOS and Android Apps</title>
         <link>http://sumitk.net/portfolio/totalwod-web-ios-and-android-apps</link>
         <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;p&gt;TotalWOD Web, iOS and Android Apps&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://totalwod.com&quot;&gt;http://totalwod.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-small field-type-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Small Description:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;TotalWOD Web, iOS and Android Apps&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-image field-type-image field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Image:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;img src=&quot;http://sumitk.net/sites/default/files/styles/blog_item_fullnode/public/itunes_512x512.png&quot; width=&quot;512&quot; height=&quot;512&quot; alt=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-show-home field-type-list-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Show in Home Page slide:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;Yes&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">3 at http://sumitk.net</guid>
         <pubDate>Tue, 03 Jan 2012 01:15:16 +0000</pubDate>
      </item>
      <item>
         <title>DrupalCon Denver iOS and Android Apps</title>
         <link>http://sumitk.net/portfolio/drupalcon-denver-ios-and-android-apps</link>
         <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;p&gt;DrupalCon Denver iOS and Android Apps&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-small field-type-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Small Description:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;DrupalCon Denver iOS and Android Apps&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-image field-type-image field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Image:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;img src=&quot;http://sumitk.net/sites/default/files/styles/blog_item_fullnode/public/default_3.png&quot; width=&quot;480&quot; height=&quot;800&quot; alt=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-show-home field-type-list-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Show in Home Page slide:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;Yes&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">2 at http://sumitk.net</guid>
         <pubDate>Tue, 03 Jan 2012 01:13:52 +0000</pubDate>
      </item>
      <item>
         <title>Hardly Strictly Bluegrass Festival Apps</title>
         <link>http://sumitk.net/portfolio/hardly-strictly-bluegrass-festival-apps</link>
         <description>&lt;div class=&quot;field field-name-body field-type-text-with-summary field-label-hidden&quot;&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;p&gt;Hardly Strictly Bluegrass Festival Apps&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-small field-type-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Small Description:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;Hardly Strictly Bluegrass Festival Apps&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-image field-type-image field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Image:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;&lt;img src=&quot;http://sumitk.net/sites/default/files/styles/blog_item_fullnode/public/Default_4.png&quot; width=&quot;640&quot; height=&quot;960&quot; alt=&quot;&quot;/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;field field-name-field-show-home field-type-list-text field-label-above&quot;&gt;&lt;div class=&quot;field-label&quot;&gt;Show in Home Page slide:&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;field-items&quot;&gt;&lt;div class=&quot;field-item even&quot;&gt;No&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">1 at http://sumitk.net</guid>
         <pubDate>Tue, 03 Jan 2012 01:12:49 +0000</pubDate>
      </item>
      <item>
         <title>3D, Sockets, and Native Android with Appcelerator Titanium</title>
         <link>http://savagelook.com/blog/portfolio/3d-sockets-and-native-android-with-appcelerator-titanium</link>
         <description>Here's the 3 part 'Twisti' app series of screencasts I did for the Appcelerator developer blog&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/3d-sockets-and-native-android-with-appcelerator-titanium&quot;&gt;3D, Sockets, and Native Android with Appcelerator Titanium&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3446</guid>
         <pubDate>Fri, 02 Dec 2011 14:22:05 +0000</pubDate>
         <content:encoded><![CDATA[<p>Yeah, yet another cross-post from the Appcelerator Developer blog. This was a fun one, though, where I got to show off some really cool features and functionality of the <a rel="nofollow" target="_blank" href="http://wiki.appcelerator.org/display/guides/Quick+Start">Titanium platform</a>. There&#8217;s a lot covered so it&#8217;s stretched over a 3 part series. I&#8217;ve brought them all together here for your viewing pleasure. The <b>original blog post links</b> included with each video contain links for all the source code and references associated with each video.</p>
<p>Here&#8217;s the 10 second summary of each part:</p>
<ol>
<li>Create a <a rel="nofollow" target="_blank" href="http://wiki.appcelerator.org/display/guides/Android+Module+Development+Guide">native Android module</a> to determine a device&#8217;s physical orientation as <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Azimuth#Navigation">azimuth</a>, pitch, and roll</li>
<li>Use the above data to animate and render a 3D model using a <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.UI.WebView-object">Titanium WebView</a> &lt;canvas&gt; and <a rel="nofollow" target="_blank" href="https://github.com/mrdoob/three.js/">Three.js</a></li>
<li>Represent this 3D model on multiple remote client devices simultaneously using high volume, realtime network communication via <a rel="nofollow" target="_blank" href="http://wiki.appcelerator.org/display/guides/Sockets">Titanium Sockets</a></li>
</ol>
<hr />
<h2>Part 1 &#8211; Native Android Module</h2>
<p><b>&gt;&gt;&gt;</b> <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/11/forging-titanium-episode-14-twisti-part-1-android-module.html">Original blog post</a><br />
</p> 
<hr />
<h2>Part 2 &#8211; 3D With Three.js</h2>
<p><b>&gt;&gt;&gt;</b> <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/11/forging-titanium-episode-15-twisti-part-2-3d-with-three-js.html">Original blog post</a><br />
</p> 
<hr />
<h2>Part 3 &#8211; Sockets</h2>
<p><b>&gt;&gt;&gt;</b> <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/12/forging-titanium-episode-16-twisti-part-3-sockets.html">Original blog post</a><br />
</p> 
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/3d-sockets-and-native-android-with-appcelerator-titanium">3D, Sockets, and Native Android with Appcelerator Titanium</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3446"></div>]]></content:encoded>
      </item>
      <item>
         <title>Forms with Appcelerator Titanium</title>
         <link>http://savagelook.com/blog/portfolio/forms-with-appcelerator-titanium</link>
         <description>A screencast on the highly unsexy, yet necessary, task of creating forms in mobile applications&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/forms-with-appcelerator-titanium&quot;&gt;Forms with Appcelerator Titanium&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3429</guid>
         <pubDate>Fri, 14 Oct 2011 12:49:53 +0000</pubDate>
         <content:encoded><![CDATA[<p>I don&#8217;t cross post often from the <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/">developer blog over at Appcelerator</a>, but people seem to be liking this screencast so I thought I&#8217;d share. I put together some code and a video showing off how you can you use cross platform design, modular Javascript, and of course, Titanium to deliver a simplified interface for creating forms in your mobile apps. Aside from it being easy for developers to implement, there&#8217;s also a special focus on making the forms as easy to navigate as possible for the end user.</p>
<p>I&#8217;ve tried not to overpopulate this blog with Appcelerator content ever since joining them as a platform evangelist. I think I&#8217;ve earned an Appcelerator post though after talking exclusively about PhoneGap and Adobe in my last one though. <img src='http://savagelook.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley'/> </p>
<p></p> 
<h2>Additional Resources</h2>
<ul>
<li><a rel="nofollow" target="_blank" href="https://github.com/appcelerator-developer-relations/Forging-Titanium/tree/master/ep-010/Forms">Forms app on Github</a></li>
<li><a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/08/forging-titanium-episode-1-commonjs-modules.html">Forging Titanium Episode 1: CommonJS Modules</a></li>
</ul>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/forms-with-appcelerator-titanium">Forms with Appcelerator Titanium</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3429"></div>]]></content:encoded>
      </item>
      <item>
         <title>Adobe &amp; PhoneGap: Makes Sense, Mostly</title>
         <link>http://savagelook.com/blog/portfolio/adobe-phonegap-makes-sense-mostly</link>
         <description>Adobe acquired Nitobi... What does this mean for Adobe, PhoneGap, and mobile developers everywhere?&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/adobe-phonegap-makes-sense-mostly&quot;&gt;Adobe &amp;#038; PhoneGap: Makes Sense, Mostly&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3370</guid>
         <pubDate>Mon, 10 Oct 2011 12:57:05 +0000</pubDate>
         <content:encoded><![CDATA[<style>
.pquote {
float:left;width:8em;color:#000;background:#ddd;font-weight:bold;font-size:18px;padding:0.5em 1em 0.5em 1em;margin:0 0.5em 0.5em 0;}</style>
<h2>Adobe Acquires Nitobi</h2>
<div style="clear:both;"></div>
<p>So if you haven&#8217;t heard yet, <a rel="nofollow" target="_blank" href="http://www.phonegap.com/2011/10/03/nitobi-enters-into-acquisition-agreement-with-adobe-2/">Adobe acquired Nitobi</a>, the company that is responsible for PhoneGap. This was announced at Adobe&#8217;s big <a rel="nofollow" target="_blank" href="http://max.adobe.com/">MAX conference</a>. If you are unfamiliar with PhoneGap, then this post is going to be wildly uninteresting to you. At a high level, they provide a cross platform mobile development solution that leverages native webviews with HTML5, CSS, and Javascript to create native mobile apps.</p>
<h2>Not Hard To See Coming</h2>
<p>Well, for one thing, Adobe was obviously hedging its bets on Flash/Air&#8217;s viability in the long term with mobile when they started introducing HTML5 capabilities through <a rel="nofollow" target="_blank" href="http://labs.adobe.com/technologies/edge/">Edge</a>. I mean, if Adobe&#8217;s planning to offer interactive, Flash-like development with HTML5, who is going to believe that Flash itself has a real future with mobile? Or as Gizmodo put it, <a rel="nofollow" target="_blank" href="http://gizmodo.com/5826448/adobe-ditches-flash-for-adobe-edge">Adobe Edge may become the beginning of the end for Flash</a>. Yeah, it will likely always exist, but it is <em>not</em> the de facto standard for delivering interactive web (or mobile) content anymore.</p>
<p></p> 
<p>And of course there&#8217;s the whole Adobe Air for mobile thing. Android was obliging enough to make Air a first class citizen. Install Air, run Air apps&#8230; simple. And while the Adobe Air install is a bit hefty, it&#8217;s hardly something worth worrying about with today&#8217;s storage capabilities on mobile devices.</p>
<blockquote class="pquote">
<p>&#8220;Flash has been labeled an outlaw and Air is smuggled in like an illegal immigrant&#8221;</p>
</blockquote>
<p>The more harrowing journey for Adobe has been iOS. Basically, Flash has been labeled an outlaw and Air is smuggled in like an illegal immigrant. There&#8217;s been a staring contest between Adobe and Apple for a while now, but I think it&#8217;s safe to say Adobe blinked. Apple has continually proven that is has the most marketable mobile devices available, and has done so without any back pedaling on what they will and will not allow (minus <a rel="nofollow" target="_blank" href="http://www.apple.com/pr/library/2010/09/09Statement-by-Apple-on-App-Store-Review-Guidelines.html">letting 3rd parties build apps</a>).</p>
<p>Something had to give if Adobe was going to get a real foothold in the mobile world, and it obviously wasn&#8217;t coming in the form of their current solutions. Enter PhoneGap&#8230;</p>
<h2>But PhoneGap is not Without Its Challenges</h2>
<p>
<div style="float:right;font-size:80%;">
<table>
<tr>
<td><img src="http://savagelook.com/blog/wp-content/uploads/2011/10/stock-senchaandjquery.jpg"/></td>
</tr>
<tr>
<td style="text-align:center;">Image by <a rel="nofollow" target="_blank" href="http://twitter.com/#!/tysoncadenhead">Tyson Cadenhead</a></td>
</tr>
</table>
</div>
<p>PhoneGap fills a lot of holes for Adobe, but its going to need a lot of help itself. I think PhoneGap has gone about as far as it can on its own. It has achieved its goal of abstracting most native functionality for many different mobile platforms, but starting developers are wanting more. </p>
<p>PhoneGap has no user interface components. This is <strong><em>not</em></strong> fun for new developers&#8230; or veteran ones for that matter. You need to build everything from scratch or go out and find a UI framework that works for you. The 2 front-runners, <a rel="nofollow" target="_blank" href="http://www.sencha.com/products/touch/">Sencha Touch</a> and <a rel="nofollow" target="_blank" href="http://jquerymobile.com/">jQuery Mobile</a>, bring their own glitches and idiosyncrasies. Also, now you find yourself learning 2 frameworks that have a noticeable lack of cross-over documentation. </p>
<p>There&#8217;s also a seemingly purposeful lack of direction in terms of tooling and best practices. New developers, often web developers, are left to their own devices to find the workflow that works best for them. There&#8217;s no sanctioned IDE or set of tools suggested from PhoneGap to build your mobile apps. Infinite flexibility can be a real drag when you just want to know the most effective way to get things done.</p>
<h2>But let&#8217;s put this even more plainly&#8230;</h2>
<p>What are the pros and cons of <b>PhoneGap</b>?</p>
<table>
<tr>
<td><span style="font-weight:bold;font-size:14px;color:#880000;">Pros</span></td>
<td><span style="font-weight:bold;font-size:14px;color:#880000;">Cons</span></td>
</tr>
<tr>
<td style="width:300px;vertical-align:top;">
<ul>
<li>Terrific mobile platform compatibility</li>
<li>It&#8217;s an open, standards-based solution</li>
<li>Ease of entry for existing web developers</li>
<li>Large existing userbase for the above reason</li>
</ul>
</td>
<td style="width:300px;vertical-align:top;">
<ul style="margin-bottom:0;padding-bottom:0;">
<li>No clear direction on UI, tooling, or best practices</li>
<li>performance is limited by webview</li>
<li>Platform disparities</li>
<li>Documentation is brief and sometimes lacking</li>
</ul>
</td>
</tr>
</table>
<p>And what are the pros and cons of <b>Adobe</b>?</p>
<table>
<tr>
<td><span style="font-weight:bold;font-size:14px;color:#880000;">Pros</span></td>
<td><span style="font-weight:bold;font-size:14px;color:#880000;">Cons</span></td>
</tr>
<tr>
<td style="width:300px;vertical-align:top;">
<ul>
<li>High quality tools for integrating development and design workflows</li>
<li>With Flash and Flex, they&#8217;ve been delivering visual and UI sugar for a long time now</li>
<li>They&#8217;ve been rocking interaction before &lt;canvas&gt; was in diapers</li>
<li>They run nearly identical user experiences on each platform via Flash/Air</li>
<li>Their documentation is nothing if not expansive</li>
<li>A vehemently loyal community</li>
</ul>
</td>
<td style="width:300px;vertical-align:top;">
<ul>
<li>Weak mobile platform compatibility. Android made Air a first class citizen, but we all know the story with iOS. </li>
<li>The majority of Adobe&#8217;s tools and SDKs are closed and proprietary</li>
<li>Has not seen a lot of fresh blood lured in by their current mobile development offerings</li>
<li>You gotta pick up AS3 if you want to be effective</li>
</ul>
</td>
</tr>
</table>
<p>Anyone else seeing a pretty clear yin-yang thing going on here?</p>
<h2>So What Does It All Mean?</h2>
<p>Well, for one thing, it means <a rel="nofollow" target="_blank" href="http://arstechnica.com/open-source/news/2011/10/phonegap-to-become-an-apache-project-as-adobe-acquires-nitobi.ars">PhoneGap is becoming an Apache project</a>. Yep, they are donating PhoneGap to Apache, which puts them one step closer to their altruistic goal of PhoneGap itself becoming obsolete. PhoneGap&#8217;s own Brian Leroux stated in his <a rel="nofollow" target="_blank" href="http://www.slideshare.net/brianleroux/phonegap-10">PhoneGap 1.0 presentation</a> that:</p>
<blockquote>
<p style="font-weight:bold;">&#8220;The purpose of PhoneGap is for PhoneGap to cease to exist&#8221;</p>
</blockquote>
<p>Why, oh why, did Adobe buy it then? I think it&#8217;s because they want to be your one stop shop for purchasing IDEs, frameworks, professional services, etc&#8230; Adobe is likely banking on the ongoing popularity of PhoneGap and web-based native mobile development. &#8220;Web-based native&#8221;&#8230; sounds a little like an oxymoron, but whatever.</p>
<h2>A Match Made in Heaven, Right?</h2>
<p>Sounds like a perfect match. The 2 companies seem to complement each other very well. But&#8230;</p>
<p>There&#8217;s just a few questions I still have regarding the acquisition. Rather than drone on any longer inserting my own conjecture, I&#8217;ll just list my questions here and leave them as talking points for you, my readers. </p>
<blockquote class="pquote" style="float:right;">
<p>&#8220;I can already hear the `It&#8217;s back to AS1` complaints starting&#8230;&#8221;</p>
</blockquote>
<ul>
<li>What happens to Flash/Air for mobile? It obviously won&#8217;t be forsaken, but this can&#8217;t sit real well with developers who have so far devoted themselves to this workflow.</li>
<li>How does Adobe deal with the inevitability that current developers will revolt against using Javascript? I can already hear the &#8220;It&#8217;s back to AS1&#8243; complaints starting&#8230;</li>
<li>Does Adobe even have any interest in getting existing AS3 developers using PhoneGap? I know they are saying that they weill support both solutions, but come on, someone is gonna get more love than the other.</li>
<li>How long until we finally see a defined workflow and IDE for PhoneGap. Is Dreamweaver integration the best we get?</li>
<li>What will the PhoneGap guys do next? They are actively working to put themselves out of a job, so I&#8217;m curious what the next move is.  </li>
</ul>
<h2>What&#8217;s Next?</h2>
<p>I have no clue, but it&#8217;s sure to be interesting. I&#8217;m hoping for good things on both sides as it&#8217;s only going to make mobile development in general more exciting. </p>
<p><img src="http://savagelook.com/blog/wp-content/uploads/2011/10/adobe-hearts-html5.png"/></p>
<p>Will Adobe&#8217;s ability to create great tools translate to mobile success? Will PhoneGap&#8217;s strict adherence to the open web model jive well with Adobe&#8217;s history of closed, proprietary tools? Will the inevitable merge of the open web  and existing Adobe community be a bumpy one? </p>
<p>Stay tuned&#8230;</p>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/adobe-phonegap-makes-sense-mostly">Adobe &#038; PhoneGap: Makes Sense, Mostly</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3370"></div>]]></content:encoded>
      </item>
      <item>
         <title>5 Annoying Things About Mac OS X Lion and How To Fix Them</title>
         <link>http://savagelook.com/blog/portfolio/5-annoying-things-about-mac-os-x-lion-and-how-to-fix-them</link>
         <description>Think some of the Mac OS X Lion changes are a pain? Me too. Here's how to fix them&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/5-annoying-things-about-mac-os-x-lion-and-how-to-fix-them&quot;&gt;5 Annoying Things About Mac OS X Lion and How To Fix Them&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3348</guid>
         <pubDate>Wed, 31 Aug 2011 12:38:13 +0000</pubDate>
         <content:encoded><![CDATA[<h2>So you&#8217;re running Mac OS X Lion&#8230;</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<p>Let me start by saying that among the <a rel="nofollow" target="_blank" href="http://www.apple.com/macosx/whats-new/features.html">250+ new features</a> added in Lion, there are some really useful ones. Some of my favorites include:</p>
<ul>
<li><strong>Accessible from App Store</strong> &#8211; The fact that the upgrade itself is accessible from the App Store is extremely convenient. Granted, you could argue that Lion is little more than the equivalent of a Windows Service Pack, which are free and automatically delivered. </li>
<li><strong>Face Time</strong> &#8211; Face Time is no longer beta as it was with Snow Leopard and is fully integrated into Lion.</li>
<li><strong>Document locking</strong> &#8211; This grants you the ability to lock documents to prevent unwanted modifications. Not groundbreaking (see &#8216;read-only&#8217;), but the stuff Lion does behind the scenes, like automatically locking old documents, is pretty nice.</li>
<li><strong>Full disk encryption</strong> &#8211; No more is only your Home path safe. As of Lion, FileVault has been totally revamped and your entire disk will now be encrypted. </li>
<li><strong>Full screen apps</strong></li>
<li><strong>Resize windows from any edge</strong></li>
</ul>
<p>In addition to these nicer features, Lion did some really annoying stuff to user interaction and the user interface. I&#8217;m all for change for the better, but most of these fall under the category of &#8220;If it ain&#8217;t broke, don&#8217;t fix it.&#8221; Fortunately, there&#8217;s ways to get back the settings you expect. Here&#8217;s 5 I specifically ran into.</p>
<div style="height:15px;"></div>
<h2>Unhide ~/Library</h2>
<hr style="padding:0;margin:0;"/>
<p>For whatever reason, Apple decided to hide your <i>~/Library</i> path. This is a real pain the ass if you find yourself in there a lot. For example, Appcelerator installs its SDK and other files in <i>~/Library/Application Support/Titanium</i>. I&#8217;m constantly tinkering in that directory and it would be nice to see it in Finder. </p>
<p>Execute this line in Terminal and you&#8217;ll have your <i>Library</i> visible once again. <strong>USERNAME</strong> is your username:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">chflags nohidden <span style="color:#000000;font-weight:bold;">/</span>users<span style="color:#000000;font-weight:bold;">/</span>USERNAME<span style="color:#000000;font-weight:bold;">/</span>Library</pre></div></div>

<div style="height:15px;"></div>
<h2>Disable &#8220;Natural&#8221; scrolling</h2>
<hr style="padding:0;margin:0;"/>
<p>Lion has included &#8220;natural&#8221; scrolling. I use quotations around &#8220;natural&#8221; because it feels anything other than natural for the average user. The content you are scrolling will now move in the direction you scroll, which is essentially the opposite of how it has always worked.</p>
<p>I have no problem with this functionality. What I do take issue with is that this was made the default behavior. To set scrolling back to the way most of us expect it, open <strong>System Settings</strong>, go to <strong>Trackpad/Mouse</strong>, and in the <strong>Scroll/Zoom</strong> tab uncheck <strong>&#8220;Scroll direction: natural&#8221;</strong>.</p>
<p><img src="https://img.skitch.com/20110831-83ricxbahiq22edfpmfncnwp6c.jpg" alt="screen" title=""/></p>
<div style="height:15px;"></div>
<h2>Fix 3 finger horizontal swipe navigation</h2>
<hr style="padding:0;margin:0;"/>
<p>The trackpad gesture I use more than any other is navigation using 3 finger swipes. I don&#8217;t even remember the last time I manually pressed the back button in a browser. No wait, yes I do. It was when I got my MacBook Air and it had Lion on it.</p>
<p>Turns out Apple mapped 2 finger horizontal swipes to its <strong>&#8220;Swipe between pages&#8221;</strong> functionality by default. Unfortunately, unless you switch this value to use 3 finger horizontal swipes, it won&#8217;t work for browser navigation. Check out the image below to see how:</p>
<p><img src="https://img.skitch.com/20110831-8unxrw8wbw5mum9ex61pmn4yha.jpg" alt="" title=""/></p>
<div style="height:15px;"></div>
<h2>Get Rid of LaunchPad</h2>
<hr style="padding:0;margin:0;"/>
<p>If I wanted what is effectively a &#8220;Show Desktop&#8221; button combined with an applications list, I&#8217;d use Windows. Just remove that thing from your Dock and be done with it.</p>
<p>Do yourself a favor. If you really want an effective way to find and run apps, check out <a rel="nofollow" target="_blank" href="http://www.alfredapp.com/">Alfred</a> or <a rel="nofollow" target="_blank" href="http://qsapp.com/">Quicksilver</a>. You can thank me later.</p>
<div style="height:15px;"></div>
<h2>Get a Fresh Restart</h2>
<hr style="padding:0;margin:0;"/>
<p>I don&#8217;t know about you, but I reboot my Mac really infrequently. When I do, though, it&#8217;s generally because I want a clean slate. I want all my apps closed and everything to go back to a fresh state. Lion disagrees with me.</p>
<p>By default Lion will remember every app you had open and make sure everything is just as you left it when you restarted your computer. For those of you who would also like a fresh restart, open <strong>System Settings</strong> and go to <strong>General</strong>. In there you just need to uncheck the <strong>&#8220;Restore windows when quitting and re-opening apps&#8221;</strong> checkbox.</p>
<p><img src="https://img.skitch.com/20110831-nugs2uasgdk7u3u51im5jw181m.jpg" alt="" title=""/></p>
<div style="height:15px;"></div>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/5-annoying-things-about-mac-os-x-lion-and-how-to-fix-them">5 Annoying Things About Mac OS X Lion and How To Fix Them</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3348"></div>]]></content:encoded>
      </item>
      <item>
         <title>Android Intents in Appcelerator</title>
         <link>http://savagelook.com/blog/portfolio/android-intents-in-appcelerator</link>
         <description>This time instead of receiving Android Intents in Appcelerator, we'll be sending them&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/android-intents-in-appcelerator&quot;&gt;Android Intents in Appcelerator&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3336</guid>
         <pubDate>Fri, 26 Aug 2011 18:47:42 +0000</pubDate>
         <content:encoded><![CDATA[<h2>Link To Full Blog Post</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<ul style="padding-top:15px;">
<li><a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/08/android-intents.html"><span style="font-size:large;">Android Intents on the Appcelerator Developer Blog</span></a></li>
</ul>
<h2>Here We Go Again</h2>
<hr style="padding:0;margin:0;"/>
<p>OK, well I just did a post on how to use Android Intent Filters with Appcelerator, so why not the other side of the coin. This time you&#8217;ll learn how you can <b><i>send</i></b> Intents instead of receiving them. With this powerful native functionality you&#8217;ll be able to leverage existing apps on your Android device to do some of your heavy lifting, like sharing images, sending text, and a whole bunch of other things.</p>
<table>
<tr>
<td><img src="http://developer.appcelerator.com.s3.amazonaws.com/blog/post_images/intents/highlight.png" border="1"/></td>
<td><img src="http://developer.appcelerator.com.s3.amazonaws.com/blog/post_images/intents/text%20intent%20list_small.png" border="1"/></td>
<td><img src="http://developer.appcelerator.com.s3.amazonaws.com/blog/post_images/intents/intent%20list_small.png" border="1"/></td>
<td><img src="http://developer.appcelerator.com.s3.amazonaws.com/blog/post_images/intents/google%20plus.png" border="1"/></td>
</tr>
</table>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/android-intents-in-appcelerator">Android Intents in Appcelerator</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3336"></div>]]></content:encoded>
      </item>
      <item>
         <title>Android Intent Filters in Appcelerator</title>
         <link>http://savagelook.com/blog/portfolio/android-intent-filters-in-appcelerator</link>
         <description>Use Android Intent Filters to make your Appcelerator apps receive Intents from other Android applications&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/android-intent-filters-in-appcelerator&quot;&gt;Android Intent Filters in Appcelerator&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3314</guid>
         <pubDate>Thu, 25 Aug 2011 16:44:47 +0000</pubDate>
         <content:encoded><![CDATA[<h2>Link To Full Blog Post</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<ul style="padding-top:15px;">
<li><a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/08/android-intent-filters.html"><span style="font-size:large;">Android Intent Filters on the Appcelerator Developer Blog</span></a></li>
</ul>
<h2>It Starts&#8230;</h2>
<hr style="padding:0;margin:0;"/>
<p>Here&#8217;s just a cross post of my first tutorial on the <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/">Appcelerator Developer Blog</a>. It details how you can use Android Intent Filters to make your Appcelerator apps receive Intents from other Android applications. For example, I&#8217;m sure if you are an Android user you are familiar with the SEND Intent list:</p>
<p><img alt="Intent List" src="http://img.skitch.com/20110824-miirycem9smeikc864q2c2gnt5.jpg" title="Intent List" width="240" height="427"/></p>
<p>With this blog post I&#8217;ll show you how you can add your app to that list. It&#8217;s a great example of how Appcelerator still leverages powerful native functionality, both visual and non-visual, while it provides a cross platform solution.</p>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/android-intent-filters-in-appcelerator">Android Intent Filters in Appcelerator</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3314"></div>]]></content:encoded>
      </item>
      <item>
         <title>Code Once, Adapt Everywhere</title>
         <link>http://savagelook.com/blog/portfolio/code-once-adapt-everywhere-mobile</link>
         <description>&quot;Code once, run everywhere&quot; might not be the mentality you should have for your cross platform mobile development&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog/portfolio/code-once-adapt-everywhere-mobile&quot;&gt;Code Once, Adapt Everywhere&lt;/a&gt; is a post from: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://savagelook.com/blog&quot;&gt;SavageLook.com&lt;/a&gt;&lt;/p&gt;</description>
         <guid isPermaLink="false">http://savagelook.com/blog/?p=3297</guid>
         <pubDate>Sat, 20 Aug 2011 22:14:32 +0000</pubDate>
         <content:encoded><![CDATA[<h2>CORE</h2>
<div style="clear:both;"></div>
<hr style="padding:0;margin:0;"/>
<p>For the sake of not repeating myself I&#8217;m going to refer to the phrase &#8220;code once, run everywhere&#8221; as <strong>CORE</strong> from here on in. Who knows, maybe it&#8217;ll catch on.  And on to the blog post&#8230;</p>
<p>So as you may have heard by now, I&#8217;ll be starting my new job as an <a rel="nofollow">Appcelerator</a> platform evangelist on Monday. If you&#8217;ve read some of my past blog posts, you&#8217;ve probably noted that I&#8217;ve been pretty critical of cross platform mobile solutions. From a developer&#8217;s perspective, we are expecting the coveted CORE, but are often left wanting. </p>
<p>What you&#8217;ll quickly find in the world of mobile development is that cross platform does not always equal CORE. </p>
<p>Rather than bemoan the shortcomings of each mobile framework, I&#8217;d rather talk about something I heard <a rel="nofollow" target="_blank" href="http://twitter.com/#!/kevinwhinnery">Kevin Whinnery</a> say during the Appcelerator <a rel="nofollow" target="_blank" href="http://vimeopro.com/appcelerator/building-native-mobile-applications">online training videos</a>. He stated that Appcelerator does not aim to be a CORE technology, but instead a <strong>&#8220;code once, <em>adapt</em> everywhere&#8221;</strong> one. Not quite as sexy, but perhaps an even more intriguing philosophy. Let&#8217;s discuss why.</p>
<h2>Web Based vs. Appcelerator</h2>
<hr style="padding:0;margin:0;"/>
<p><em>For a quick summary of how Appcelerator is fundamentally different than web-based cross platform mobile frameworks, <a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/phonegap-is-web-based-appcelerator-is-pure-javascript">read here</a>.</em></p>
<p>Aside from near-native performance, what&#8217;s the biggest advantage of using Appcelerator over web based mobile frameworks like <a rel="nofollow" target="_blank" href="http://www.phonegap.com/">Phonegap</a> or <a rel="nofollow" target="_blank" href="http://rhomobile.com/">Rhomobile</a>? Its ability to use the device&#8217;s native UI components. And no, I don&#8217;t mean it has UI components skinned to look like native components, like many of the web-based solutions. I mean it actually uses the platform&#8217;s native, performant UI in the app.</p>
<p>With native UI we can build apps that are indistinguishable from apps built with Objective-C or Java. The look, feel, performance, and behavior will be exactly what is expected of the given platform. Plus, we don&#8217;t have to build them ourselves. </p>
<p>To achieve this level of quality, though, <strong>you need to be willing to adapt your app, not just design for the lowest common denominator</strong>, as is often the mentality with CORE apps. Sure, you can use the iPhone&#8217;s slick Navigation Controller bar on all versions of your app, but is that what Android users are expecting? Nor would an Android Spinner be befitting of an iPhone app.</p>
<table>
<tr>
<td>
<img src="http://savagelook.com/blog/wp-content/uploads/2011/08/spinner.png" alt="Spinner" title=""/></td>
<td>
<img src="http://savagelook.com/blog/wp-content/uploads/2011/08/nav_good.png" alt="Navigation Bar" title=""/></td>
</tr>
</table>
<p>You see, in some cases, CORE apps come at the expense of the most important factor: the user experience. </p>
<h2>Why Bother?</h2>
<hr style="padding:0;margin:0;"/>
<p>Many people, particularly proponents of web based mobile development, are of the opinion that native UI components are not necessary to deliver a high quality user experience. I agree, in certain circumstances. Games, novelty utilities (think <a rel="nofollow" target="_blank" href="https://market.android.com/details?id=com.devuni.flashlight&amp;feature=search_result">Flashlight</a>), and otherwise simple apps are good examples that probably don&#8217;t benefit much from a native experience.</p>
<p>In my opinion, though, it&#8217;s a necessity for more complex apps, particularly ones leveraging native APIs, to use the UI that is  familiar to the device. They need to work in a simple, intuitive manner as mobile users can be quick on the trigger in deeming an app unfriendly. Those who have spent time developing for multiple platforms understand that <strong>the users of each platform have different expectations</strong>. </p>
<p>I don&#8217;t want a navigation bar in my Android app. I want my tabs at the bottom on iPhone, the top on Android. I want to press my menu button on Android to get my app&#8217;s options. I want my system buttons to look familiar. I want to pull to refresh on my iPhone. </p>
<p>Let me be clear that both Appcelerator and web-based frameworks have the ability to adapt their apps to supported platforms. And I don&#8217;t just mean churning out a basic app, I mean creating a high quality, native app. Depending on your point of view, however, one may be much more appealing than the other.</p>
<h2>Attending to the UI (Web-based)</h2>
<hr style="padding:0;margin:0;"/>
<table>
<tr>
<td>
<img src="http://savagelook.com/blog/wp-content/uploads/2011/08/jquery-mobile.png" alt="jQuery Mobile" title="" height="360" width="240"/></td>
<td>
<img src="http://savagelook.com/blog/wp-content/uploads/2011/08/hero-sencha-touch-1.0.jpg" alt="Sencha Touch" title=""/></td>
</tr>
</table>
<p>With web-based solutions, the app exists in a web view container. This means that you are effectively building a native app that consists of only a web view which hosts a web application. <strong>You have no native components with which to work</strong>. This leaves us with 2 options for building the UI of the app (super quick assessment coming): </p>
<ol>
<li>Use a 3rd party framework like <a rel="nofollow" target="_blank" href="http://jquerymobile.com/">jQuery Mobile</a> or <a rel="nofollow" target="_blank" href="http://www.sencha.com/products/touch/">Sencha Touch</a>
<ul>
<li>Pros
<ul>
<li>Lots of functionality and UI components</li>
<li>Speeds up development process</li>
<li>Some, like Sencha Touch, have a very native look to their components.</li>
</ul>
</li>
<li>Cons
<ul>
<li>Web based framework UI is generally less responsive than ones created natively or with Appcelerator on mobile devices.</li>
<li>Additional learning curve for the added framework</li>
<li>You are even further removed from the native app. You now have a UI framework which sits on a native web view wrapper which then becomes a native app. Lots to know and lots of places for things to go wrong.</li>
<li>Frameworks like Sencha Touch are limited to webkit based web views (iOS, Android, BB 6.0+). This essentially removes the biggest advantage of web based frameworks, which is their compatibility.</li>
</ul>
</li>
</ul>
</li>
<li>Create the UI yourself with HTML/CSS/JS
<ul>
<li>Pros
<ul>
<li>Totally customizable for any platform </li>
<li>Its easier to manage performance and UI inconsistencies when using code for only what you need to achieve</li>
<li>No additional learning curve beyond basic web dev and understanding your web based framework of choice. </li>
</ul>
</li>
<li>Cons
<ul>
<li>Much slower to develop, as you have to build your UI from scratch. The styling of the UI to look native all falls on you or external resources you can find.</li>
<li>Even for seasoned web devs, managing cross platform mobile CSS can be a daunting task. </li>
<li>All cross browser inconsistencies become your job to address, unless you use a light JS framework like <a rel="nofollow" target="_blank" href="http://xuijs.com/">xuijs</a> or <a rel="nofollow" target="_blank" href="http://zeptojs.com/">zeptojs</a>.</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>So as you can see, web based mobile development encounters many of the same issues that traditional web development does. And the problem is compounded when you are trying to make these web based solutions look, feel, perform, and behave natively.</p>
<h2>Attending to the UI (Appcelerator)</h2>
<hr style="padding:0;margin:0;"/>
<p>Appcelerator apps are built differently. The extremely short version is that Appcelerator Javascript code is mapped to native symbols of the target platform. Any code that can&#8217;t be mapped to a native symbol is run through a Javascript interpreter. <a rel="nofollow" target="_blank" href="http://twitter.com/#!/jhaynie">Jeff Haynie</a>, CEO of Appcelerator, does a much better job of explaining it in <a rel="nofollow" target="_blank" href="http://stackoverflow.com/questions/2444001/how-does-appcelerator-titanium-mobile-work">this StackOverflow post</a>.</p>
<p>What this means that there are <strong>no 3rd party tools or special code necessary to create totally native components</strong>. You want a button that has native appearance and behavior on both iPhone and Android?</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color:#003366;font-weight:bold;">var</span> button <span style="color:#339933;">=</span> Ti.<span style="color:#660066;">UI</span>.<span style="color:#660066;">createButton</span><span style="color:#009900;">&#40;</span><span style="color:#009900;">&#123;</span>title<span style="color:#339933;">:</span><span style="color:#3366CC;">'test button'</span><span style="color:#009900;">&#125;</span><span style="color:#009900;">&#41;</span><span style="color:#339933;">;</span></pre></div></div>

<table>
<tr>
<td><img src="http://savagelook.com/blog/wp-content/uploads/2011/08/android-button.jpg" alt="Android button" title=""/></td>
<td>
<img src="http://savagelook.com/blog/wp-content/uploads/2011/08/iphone-button.jpg" alt="iPhone button" title=""/></td>
</tr>
</table>
<p>There you go, an Android and iPhone button respectively. How &#8217;bout a table view populated with sample data?</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color:#003366;font-weight:bold;">var</span> data <span style="color:#339933;">=</span> <span style="color:#009900;">&#91;</span><span style="color:#009900;">&#123;</span>title<span style="color:#339933;">:</span><span style="color:#3366CC;">&quot;Row 1&quot;</span><span style="color:#009900;">&#125;</span><span style="color:#339933;">,</span><span style="color:#009900;">&#123;</span>title<span style="color:#339933;">:</span><span style="color:#3366CC;">&quot;Row 2&quot;</span><span style="color:#009900;">&#125;</span><span style="color:#339933;">,</span><span style="color:#009900;">&#123;</span>title<span style="color:#339933;">:</span><span style="color:#3366CC;">&quot;Row 3&quot;</span><span style="color:#009900;">&#125;</span><span style="color:#339933;">,</span><span style="color:#009900;">&#123;</span>title<span style="color:#339933;">:</span><span style="color:#3366CC;">&quot;Row 4&quot;</span><span style="color:#009900;">&#125;</span><span style="color:#339933;">,</span><span style="color:#009900;">&#123;</span>title<span style="color:#339933;">:</span><span style="color:#3366CC;">&quot;Row 5&quot;</span><span style="color:#009900;">&#125;</span><span style="color:#339933;">,</span><span style="color:#009900;">&#123;</span>title<span style="color:#339933;">:</span><span style="color:#3366CC;">&quot;Row 6&quot;</span><span style="color:#009900;">&#125;</span><span style="color:#009900;">&#93;</span><span style="color:#339933;">;</span>
<span style="color:#003366;font-weight:bold;">var</span> table <span style="color:#339933;">=</span> Titanium.<span style="color:#660066;">UI</span>.<span style="color:#660066;">createTableView</span><span style="color:#009900;">&#40;</span><span style="color:#009900;">&#123;</span>data<span style="color:#339933;">:</span>data<span style="color:#009900;">&#125;</span><span style="color:#009900;">&#41;</span><span style="color:#339933;">;</span></pre></div></div>

<table>
<tr>
<td><img src="http://savagelook.com/blog/wp-content/uploads/2011/08/android-table.jpg" alt="Android table view" title=""/></td>
<td>
<img src="http://savagelook.com/blog/wp-content/uploads/2011/08/iphone-table.jpg" alt="iPhone table view" title=""/></td>
</tr>
</table>
<p>Yep, it&#8217;s that simple. The iPhone table will even have the bounce scrolling users expect. You have the same simplicity that web based UI frameworks solutions provide, except you are additionally getting native look, feel, performance, and behavior. The components are even designable as you would expect them to be.</p>
<p>The one drawback to this simplicity is that without careful attention to your code, you can end up with a mess of interlacing UI and logic. Android has XML for layout, iOS has .nib/.xib files, web based solutions have HTML/CSS. Appcelerator, <em>for the time being</em>, relies solely on your Javascript code. Javascript MVC frameworks, like <a rel="nofollow" target="_blank" href="http://puremvc.org/">PureMVC</a>, and attention to best practices (as mentioned in the <a rel="nofollow" target="_blank" href="http://vimeopro.com/appcelerator/building-native-mobile-applications">online training videos</a>) can mitigate this risk. There are even some vague rumblings of a more declarative syntax for UI design in the future&#8230; </p>
<h2>Adaptation</h2>
<hr style="padding:0;margin:0;"/>
<p>So now that we know how UIs are built in both Appcelerator and web-based frameworks, how do we adapt them in such a way to deliver a native user experience? Despite the differences between the frameworks mentioned so far, the solution is fairly common among all frameworks. </p>
<p>While I will confidently say that Appcelerator has the abstraction that delivers the most familiar and device-specific experience, it too needs to account for usability that is not necessarily CORE. And even saying it is not CORE can be a bit of a misnomer as the same code base can be used by multiple platforms. It just requires the clever and judicious insertion of platform specific code facilitated by your mobile framework&#8217;s device identification APIs.</p>
<p>Let&#8217;s take a quick look at how Appcelerator identifies your device and can act on the information:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color:#003366;font-weight:bold;">var</span> osname <span style="color:#339933;">=</span> Titanium.<span style="color:#660066;">Platform</span>.<span style="color:#660066;">osname</span><span style="color:#339933;">;</span>
<span style="color:#000066;font-weight:bold;">if</span> <span style="color:#009900;">&#40;</span>osname <span style="color:#339933;">==</span> <span style="color:#3366CC;">'android'</span><span style="color:#009900;">&#41;</span> <span style="color:#009900;">&#123;</span>
    <span style="color:#006600;font-style:italic;">// android specific code</span>
<span style="color:#009900;">&#125;</span> <span style="color:#000066;font-weight:bold;">else</span> <span style="color:#000066;font-weight:bold;">if</span> <span style="color:#009900;">&#40;</span>osname <span style="color:#339933;">==</span> <span style="color:#3366CC;">'iphone'</span><span style="color:#009900;">&#41;</span> <span style="color:#009900;">&#123;</span>
    <span style="color:#006600;font-style:italic;">// iphone specific code</span>
<span style="color:#009900;">&#125;</span> <span style="color:#000066;font-weight:bold;">else</span> <span style="color:#000066;font-weight:bold;">if</span> <span style="color:#009900;">&#40;</span>osname <span style="color:#339933;">==</span> <span style="color:#3366CC;">'ipad'</span><span style="color:#009900;">&#41;</span> <span style="color:#009900;">&#123;</span>
    <span style="color:#006600;font-style:italic;">// ipad specific code</span>
<span style="color:#009900;">&#125;</span></pre></div></div>

<p>For a more in depth example of how you can use this logic to create truly cross platform components and functionality, check out the 6 minute screencast <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/08/forging-titanium-episode-2-a-cross-platform-navigation-controller.html">&#8220;Forging Titanium: A Cross-Platform Navigation Controller.&#8221;</a> Or just watch this:</p>
<p></p> 
<p>And for reference, let&#8217;s look at PhoneGap&#8217;s adaptation method as well, just to show the similarities:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color:#003366;font-weight:bold;">var</span> platform <span style="color:#339933;">=</span> device.<span style="color:#660066;">platform</span><span style="color:#339933;">;</span>
<span style="color:#000066;font-weight:bold;">if</span> platform <span style="color:#339933;">==</span> <span style="color:#3366CC;">'Android'</span><span style="color:#009900;">&#41;</span> <span style="color:#009900;">&#123;</span>
    <span style="color:#006600;font-style:italic;">// android specific code</span>
<span style="color:#009900;">&#125;</span> <span style="color:#000066;font-weight:bold;">else</span> <span style="color:#000066;font-weight:bold;">if</span> platform <span style="color:#339933;">==</span> <span style="color:#3366CC;">'iPhone'</span><span style="color:#009900;">&#41;</span> <span style="color:#009900;">&#123;</span>
    <span style="color:#006600;font-style:italic;">// iphone specific code</span>
<span style="color:#009900;">&#125;</span> <span style="color:#000066;font-weight:bold;">else</span> <span style="color:#000066;font-weight:bold;">if</span> platform <span style="color:#339933;">==</span> <span style="color:#3366CC;">'BlackBerry'</span><span style="color:#009900;">&#41;</span> <span style="color:#009900;">&#123;</span>
    <span style="color:#006600;font-style:italic;">// blackberry specific code</span>
<span style="color:#009900;">&#125;</span></pre></div></div>

<p>Very similar indeed, but you need to consider the 2 prior &#8220;Attending to the UI&#8221; sections before calling them equal. Its the frequency with which you are required to apply this and other types of adaptation that affects the maintainability of your app as it grows.</p>
<h2>Minimizing Adaptation</h2>
<hr style="padding:0;margin:0;"/>
<p>It doesn&#8217;t take an expert software engineer to see that conditional checks on the device&#8217;s platform throughout your code isn&#8217;t ideal. It gets harder to maintain the more conditionals you include. It becomes apparent that we need our development framework to do most of this work for us.</p>
<p>In the case of Appcelerator, the need for conditional adaptation is minimized by the fact that you can utilize native UI components. Look back at our examples of the buttons and table views. There was no conditional code, no special handling. You get system specific components with no extra effort. </p>
<p>You really only need conditional code when you want to leverage native components that don&#8217;t have an equivalent on your other target platforms. For example, if you haven&#8217;t already, check out the <a rel="nofollow" target="_blank" href="http://developer.appcelerator.com/blog/2011/08/forging-titanium-episode-2-a-cross-platform-navigation-controller.html">Cross-Platform Navigation Controller video</a> above. It shows how you can use these conditionals to create navigation code that you can use seamlessly between iOS or Android.</p>
<p>Web based platforms also do a great job of creating an abstraction so that you don&#8217;t need to use conditionals for each supported platform. The problem, as discussed earlier, is that these abstractions don&#8217;t represent actual native components. They most often represent HTML/CSS/JS that are attempting to mimic native components. Worse yet, sometimes they are components that have no relation to existing native components, yet find themselves in native apps. As I said, this is a point of contention among mobile developers, and I&#8217;ll leave further discussion for the comments if necessary.</p>
<p>What web based frameworks can&#8217;t give you in native components, they provide in CSS, often applied dynamically via Javascript. The use of CSS is a double-edged sword. On one hand, you have a method of styling that not only allows you to skin your whole app, but also affords you the opportunity to gracefully degrade the styling based on the user&#8217;s device. This is why web based solutions typically support more platforms than ones like Appcelerator. Add all the bells and whistles like rounded corners, drop shadows, webkit transitions, etc&#8230; and if the device doesn&#8217;t support them, they will disappear without interrupting the user experience.</p>
<p>On the other hand, unless you are a CSS wizard with existing knowledge of CSS3 and how it applies to mobile, using it can be difficult. You can find yourself with mountains of CSS attempting to mimic components that are created with a single line of code in Appcelerator. For example, here&#8217;s a shiny iPhone button in pure CSS:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span> <span style="color:#00AA00;">&#123;</span>
  <span style="color:#000000;font-weight:bold;">font-family</span><span style="color:#00AA00;">:</span> <span style="color:#ff0000;">&quot;Helvetica Neue&quot;</span><span style="color:#00AA00;">,</span> Helvetica<span style="color:#00AA00;">,</span> <span style="color:#993333;">sans-serif</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">font-size</span><span style="color:#00AA00;">:</span> <span style="color:#933;">1.3em</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">font-weight</span><span style="color:#00AA00;">:</span> <span style="color:#993333;">bold</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">width</span><span style="color:#00AA00;">:</span> <span style="color:#933;">97%</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">height</span><span style="color:#00AA00;">:</span> <span style="color:#933;">50px</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">border</span><span style="color:#00AA00;">:</span> <span style="color:#933;">3px</span> <span style="color:#993333;">solid</span> <span style="color:#cc00cc;">#282726</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">background</span><span style="color:#00AA00;">:</span> -webkit-gradient<span style="color:#00AA00;">&#40;</span> linear<span style="color:#00AA00;">,</span> <span style="color:#000000;font-weight:bold;">left</span> <span style="color:#000000;font-weight:bold;">top</span><span style="color:#00AA00;">,</span> <span style="color:#000000;font-weight:bold;">left</span> <span style="color:#000000;font-weight:bold;">bottom</span><span style="color:#00AA00;">,</span> from<span style="color:#00AA00;">&#40;</span><span style="color:#cc00cc;">#e2e2e2</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> to<span style="color:#00AA00;">&#40;</span><span style="color:#cc00cc;">#8c8a88</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> color-stop<span style="color:#00AA00;">&#40;</span><span style="color:#cc66cc;">0.5</span><span style="color:#00AA00;">,</span> <span style="color:#cc00cc;">#acadae</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> color-stop<span style="color:#00AA00;">&#40;</span><span style="color:#cc66cc;">0.5</span><span style="color:#00AA00;">,</span> <span style="color:#cc00cc;">#82807e</span><span style="color:#00AA00;">&#41;</span> <span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">margin</span><span style="color:#00AA00;">:</span> <span style="color:#cc66cc;">0</span> <span style="color:#cc66cc;">0</span> <span style="color:#933;">3px</span> <span style="color:#cc66cc;">0</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">text-shadow</span><span style="color:#00AA00;">:</span> <span style="color:#933;">0px</span> <span style="color:#933;">1px</span> <span style="color:#cc66cc;">0</span> <span style="color:#cc00cc;">#cecece</span><span style="color:#00AA00;">;</span>
  -webkit-background-origin<span style="color:#00AA00;">:</span> padding-box<span style="color:#00AA00;">;</span>
  -webkit-background-<span style="color:#000000;font-weight:bold;">clip</span><span style="color:#00AA00;">:</span> border-box<span style="color:#00AA00;">;</span>
  -webkit-border-radius<span style="color:#00AA00;">:</span> <span style="color:#933;">8px</span><span style="color:#00AA00;">;</span>
<span style="color:#00AA00;">&#125;</span>
&nbsp;
input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span><span style="color:#3333ff;">:hover</span><span style="color:#00AA00;">,</span> input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span>.cancel<span style="color:#00AA00;">,</span>
input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span><span style="color:#3333ff;">:active</span><span style="color:#00AA00;">,</span> input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span><span style="color:#6666ff;">.cancel</span><span style="color:#3333ff;">:active </span><span style="color:#00AA00;">&#123;</span>
  <span style="color:#000000;font-weight:bold;">color</span><span style="color:#00AA00;">:</span> <span style="color:#cc00cc;">#fff</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">text-shadow</span><span style="color:#00AA00;">:</span> <span style="color:#993333;">none</span><span style="color:#00AA00;">;</span>
<span style="color:#00AA00;">&#125;</span>
&nbsp;
input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span><span style="color:#3333ff;">:hover</span><span style="color:#00AA00;">,</span> input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span><span style="color:#6666ff;">.cancel</span><span style="color:#3333ff;">:hover </span><span style="color:#00AA00;">&#123;</span>
  <span style="color:#000000;font-weight:bold;">background</span><span style="color:#00AA00;">:</span> -webkit-gradient<span style="color:#00AA00;">&#40;</span> linear<span style="color:#00AA00;">,</span> <span style="color:#000000;font-weight:bold;">left</span> <span style="color:#000000;font-weight:bold;">top</span><span style="color:#00AA00;">,</span> <span style="color:#000000;font-weight:bold;">left</span> <span style="color:#000000;font-weight:bold;">bottom</span><span style="color:#00AA00;">,</span> from<span style="color:#00AA00;">&#40;</span><span style="color:#cc00cc;">#aaaee5</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> to<span style="color:#00AA00;">&#40;</span><span style="color:#cc00cc;">#10006d</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> color-stop<span style="color:#00AA00;">&#40;</span><span style="color:#cc66cc;">0.5</span><span style="color:#00AA00;">,</span> <span style="color:#cc00cc;">#1F3B97</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> color-stop<span style="color:#00AA00;">&#40;</span><span style="color:#cc66cc;">0.5</span><span style="color:#00AA00;">,</span> <span style="color:#cc00cc;">#081f6f</span><span style="color:#00AA00;">&#41;</span> <span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">;</span>
<span style="color:#00AA00;">&#125;</span>
&nbsp;
input<span style="color:#00AA00;">&#91;</span>type<span style="color:#00AA00;">=</span>button<span style="color:#00AA00;">&#93;</span><span style="color:#6666ff;">.cancel</span> <span style="color:#00AA00;">&#123;</span>
  <span style="color:#000000;font-weight:bold;">background</span><span style="color:#00AA00;">:</span> -webkit-gradient<span style="color:#00AA00;">&#40;</span> linear<span style="color:#00AA00;">,</span> <span style="color:#000000;font-weight:bold;">left</span> <span style="color:#000000;font-weight:bold;">top</span><span style="color:#00AA00;">,</span> <span style="color:#000000;font-weight:bold;">left</span> <span style="color:#000000;font-weight:bold;">bottom</span><span style="color:#00AA00;">,</span> from<span style="color:#00AA00;">&#40;</span><span style="color:#cc00cc;">#5c5c5b</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> to<span style="color:#00AA00;">&#40;</span><span style="color:#cc00cc;">#1e1b16</span><span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">,</span> color-stop<span style="color:#00AA00;">&#40;</span><span style="color:#cc66cc;">0.2</span><span style="color:#00AA00;">,</span> <span style="color:#cc00cc;">#1e1b16</span><span style="color:#00AA00;">&#41;</span> <span style="color:#00AA00;">&#41;</span><span style="color:#00AA00;">;</span>
  <span style="color:#000000;font-weight:bold;">margin-top</span><span style="color:#00AA00;">:</span> <span style="color:#933;">6px</span><span style="color:#00AA00;">;</span>
<span style="color:#00AA00;">&#125;</span></pre></div></div>

<p>It does the job, but man, it is really cumbersome. Again, this is all a factor of wanting to create a native experience. Some will contest that it does not need to be this complex, that as long as the UI is uniform it does not need to conform to the native expectations. This mentality, though, is typically only held by those who back mobile frameworks that are incapable of delivering that native experience.  As the local radio sports caster in Pittsburgh likes to  say, &#8220;Not hatin&#8217;, just sayin&#8217;.&#8221;</p>
<h2>Summary</h2>
<hr style="padding:0;margin:0;"/>
<p>You can&#8217;t beat web based mobile development for platform compatibility. Every mobile device has a browser that supports HTML/CSS/JS, right? You can create UIs that work on many platforms and degrade gracefully to handle lower end devices. Quality, usable apps are totally possible with these frameworks.</p>
<p>But the user doesn&#8217;t care how compatible your app is. They just want it to work, as they expect it to, on the device of their choice. In this respect, Appcelerator is unparalleled in the realm of cross platform solutions.</p>
<p>I have a strong suspicion that web based mobile technologies are only going to get better. I mean, let&#8217;s face it, the web isn&#8217;t going to be disappearing anytime soon. It will get faster, more functional, and closer to the expectations of the mobile user, just like desktop web browsers. And I, as a soon-to-be Appcelerator employee, welcome this. </p>
<p>As web based mobile development ups it game, so shall Appcelerator. Whether you&#8217;re an Appcelerator, web based, or native developer, it&#8217;s an exciting time&#8230; no matter what side of the fence you&#8217;re on.</p>
<p><a rel="nofollow" target="_blank" href="http://savagelook.com/blog/portfolio/code-once-adapt-everywhere-mobile">Code Once, Adapt Everywhere</a> is a post from: <a rel="nofollow" target="_blank" href="http://savagelook.com/blog">SavageLook.com</a></p>
<div class="shr-publisher-3297"></div>]]></content:encoded>
      </item>
      <item>
         <title>Simple Integration of Supermodel and Appcelerator Titanium Alloy</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524621/simple-integration-of-supermodel-and-appcelerator-titanium-alloy</link>
         <description>SuperModel &amp;#38; Alloy Part One This is a simple example of integrating Supermodel with Appcelerator Titanium Alloy for one approach for dealing with relationships in Backbonejs models. Supermodel does a bunch of different things so I suggest that you take a look at the documentation for additional features. I think one of the more interesting [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>Quick Way to work with Models and Alloy in Appcelerator Titanium</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524608/quick-way-to-work-with-models-and-alloy-in-appcelerator-titanium</link>
         <description>Quick Way to work with Models and Alloy in Appcelerator Titanium For those who have taken the dive into Alloy from Appcelerator, understanding how models work can definitely simplify your overall application architecture and then you can also leverage the functionality of Backbonejs Models. Easily Saving the Models When I am working and want to get something [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>Swizzling TiExceptionHandler to better capture issues within Appcelerator Titanium IOS Applications</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524600/swizzling-tiexceptionhandler-to-better-capture-issues-within-appcelerator-titanium-ios-applications</link>
         <description>So in my IOS hacking adventures and attempts to get better log information for apps running in production, I looked into the bowels of the source code of Appcelerator Titanium. I was looking for a way to make my logging the eyes and ears of the app once it is in the wild so we [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>Alloy ListView &amp; Facebook Friends</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524584/alloy-listview-facebook-friends</link>
         <description>Alloy ListView &amp;#38; Facebook Friends Using ListViews in your application will provide you with a tremendous performance improvement in your applications. You will undoubtedly see the biggest gains in your Android applications. The functionality is not fully baked into Alloy and there are still some open issues that you can track in JIRA but for [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>Kinvey Appcelerator &amp; Facebook Integration</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524569/kinvey-appcelerator-facebook-integration</link>
         <description>Over the last week or so I have been trying to integrate Appcelerator with Parse based on client&amp;#8217;s recommendation; it does not work in a supported manner so I have moved on until Parse can address the issue. How do you integrate the @ParseIt Javascript API with @appcelerator and not use undocumented calls &amp;#8211; Stack [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>Javascript Frameworks: AngularJS</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524521/javascript-frameworks-angularjs</link>
         <description>We have been developing javascript applications here at Clearly Innovative to integrate with Appcelerator CLoud Services. We usually are building a custom content management system or an administrative console for a client. We have settled on nodejs and or Node.ACS when building these applications and have dabbled with different frameworks for the front-end of the [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>The Federal Government’s Mobile Makeover – Top 7 Most Exciting Trends</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524420/the-federal-governments-mobile-makeover-top-7-most-exciting-trends</link>
         <description>Sequestration and budget issues aside, the Federal Government is taking large strides in mobilizing its workforce – from federal civilian agencies to the DoD and Intelligence Communities.  Recently, at the MobileGovSummit, we had a chance to hear firsthand about the latest developments from the government’s top leaders.  Here is our take on the ‘status’ of [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>Enterprise Mobile Apps – How to Maximize ROI Without Sacrificing Performance or Features</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524381/enterprise-mobile-apps-how-to-maximize-roi-without-sacrificing-performance-or-features</link>
         <description>Overview: Many organizations are spending time and money to develop mobile apps – often for multiple platforms (e.g., iPhone, iPad, Android, BlackBerry, etc.).  What they often do not know is that cross-platform tools exist – allowing an app to be written in one language, one time and ‘published’ to multiple platforms, rather than hiring multiple developers [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>6 Key Themes in mHealth for Federal Research</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524159/6-key-themes-in-mhealth-for-federal-research</link>
         <description>Recently we had the opportunity to attend a Mobile Health Forum put on by ICF International near Washington, DC, entitled, “Federal Efforts to Advance Public Health and Health Research with Mobile Technology”. It was an excellent showcase of several federal efforts – past, present and future – around using mHealth to enable effective, theory-based interventions. [...]</description>
         <guid isPermaLink="false"></guid>
      </item>
      <item>
         <title>Panel Discussion at MMTC Boot Camp: Next Generation Digital Media Entrepreneur</title>
         <link>http://www.clearlyinnovative.com/blog/post/34758524115/panel-discussion-at-mmtc-boot-camp-next-generation-digital-media-entrepreneur</link>
         <description>I was part of a panel discussion at the MMTC Boot Camp titles  Boot Camp: How to Become a Next Generation Digital Media Entrepreneur. It was presented in collaboration with MMTC Broadcasting, Digital Diversity Network (DDN), and National Association of Multicultural Digital Entrepreneurs (NAMDE)* Video of panel is available here http://mmtconline.org/boot-camp-pt-ii-videos-2/</description>
         <guid isPermaLink="false"></guid>
      </item>
   </channel>
</rss>
<!-- fe3.yql.bf1.yahoo.com compressed/chunked Tue Jun 18 06:25:54 UTC 2013 -->
