Monthly Archives: September 2013

About Sencha Touch 2.x, PhoneGap/Cordova, and the iOS 7 Status Bar

arch1Well, the zany think-tank at Apple sure does seem to enjoy making our lives as cross-device mobile app developers exciting.  And by ‘exciting,’ I mean ‘Oh God, Oh God, WE’RE BLOWING OUR DEADLINE!!!’

Their latest attempt to ‘Think Different’ resulted in changing the behavior of the iOS status bar. In prior versions of iOS, your phonegap-based app ran directly underneath it. However, in iOS 7, your phonegap-based app actually runs ON TOP OF IT as illustrated by the screenshot at right.

So… that, uh.. sucks.

To resolve this issue, I came up with the following hacks:

1) In your index.html file, add the following code to your deviceready handler:

document.addEventListener("deviceready", function() {
  if (parseFloat(window.device.version) === 7.0) {
    console.log('iOS7 is the official OS of SATAN!');
    document.body.style.marginTop = "20px";
  }
  // other phonegap related stuff
});

Next, you’ll need to modify the launch() function in your Sencha Touch app.js file to reduce the size of the viewport by 20 pixels:

Ext.application({
 // bunch of code omitted for brevity...
 name: 'ArchSTL',
 isNative: true,
 launch: function() {
  if (Ext.os.is.iOS) {
    if (Ext.os.version.major >= 7) {
       if (ArchSTL.app.isNative) // manual flag to denote "native" mode
        Ext.Viewport.setHeight(Ext.Viewport.getWindowHeight() - 20);
       }
    }
  }
  // other stuff
 }
});

Ultimately this solves the problem, and you can even set the background color of the status bar by tweaking the body background color CSS style in your index.html file. In this case, we set it to the client’s complementary app color to try and reinforce their branding standards.

Here’s the final result:

archbalt2

But hey, if it was easy, everyone would be doing it…right?

Icon and Splash Screen Reference for Mobile Web/PhoneGap/Cordova Apps

If you’re a mobile web/app developer like myself, you’ve probably had to suffer with getting dirty looks from your art department as you have to go back to them repeatedly for assets to support four different mobile operating systems (iOS, Android, Blackberry, Windows Mobile 8).  In order to avoid these uncomfortable conversations, I bring you a list of all required art assets that you might need in order to get your app published and make your customers happy.

iOS Icons

  • 1024 x 1024, 72 dpi jpg/png for iTunes Connect
  • 57 x 57 for iPhone, iPod Touch
  • 114 x 114 for Retina displays
  • 72  x 72 for iPad non-retina
  • 120 x 120 for iOS 7 Phones
  • 144 x 144 for IPad w/Retina display
  • 152 x 152 for iPad w/Retina display on iOS 7

iOS Spotlight Icons

  • 29 x 29
  • 58 x 58
  • 80 x 80

iOS Settings Icons

  • 29 x 29 (iPhone non-retina)
  • 58 x 58 (iPhone Retina)

iOS Launch Images

  • 320 x 460
  • 320 x 480
  • 640 x 920
  • 640 x 960
  • 640 x 1096
  • 640 x 1136
  • 768 x 1004
  • 748 x 1024
  • 1536 x 2008
  • 1496 x 2048

iOS Startup Images (Native App)

  • 320 x 480 (3.5″ non-retina)
  • 640 x 960  (3.5″ Retina)
  • 640 x 1136 (4 inch iPhone)

Google Play Store Artwork

  • 512 x 512 32-bit PNG icon
  • 1024 x 500 png feature graphic
  • 180 x 120 promo graphic
  • Promo video on youtube

Android Splash Screens

  • xlarge (xhdpi): at least 960 x 720
  • large (hdpi): at least 640 x 480
  • medium (mdpi): at least 470 x 320
  • small (ldpi): at least 426 x 320

Highly recommended to use a 9-patch image

Android Icons

  • 72 x 72
  • 36 x 36
  • 48 x 48
  • 96 x 96

Blackberry 10.x Splash Screen

  • 768×1280 (Z10)
  • 720×720 (Q10)

Blackberry 10.x Icon

  • 114 x 114

Blackberry World

  • 480 x 480 – Store Icon
  • 1920×1186 – Product Featured Image
  • Screenshots – can’t be more than 1280 x 1280

I’ll be updating this with more details later this week…

Integrating Ext JS Combo Boxes with SalesForce.com

We’re working with a customer to integrate an Ext JS 4 UI with SalesForce.com and have run into a number of interesting challenges.

One of the issues that we ran into pertains to how remote Ext JS 4 combo boxes transmit query data to the back-end in order to perform incremental searches. Out of the box, whatever the user types into the combo box is transmitted over the uri, e.g. getmydata.aspx?query=somethingITypedIntoAComboBox. The problem is that the salesforce transport mechanism that we’re using only carries forward data passed in the http header, ignoring everything passed on the url.

We wound up modifying the combo box to transmit query data over a Store’s proxy header by setting up a combo box listener that dynamically changed the related store’s proxy header as illustrated below:

{
 xtype: 'combo',
 listeners: {
   beforequery: function(queryPlan,eopts) {
       this.store.on('beforeload', function(store,operations,eopts) {
          Ext.apply(store.proxy.headers, { 
                      query:queryPlan.query 
          });
       });
   },
   afterquery: function(queryPlan,eopts) {
      this.store.un('beforeload');
      store.proxy.headers.query=null;
   }
 },
 store: s,
 displayField: 'Name',
 valueField: 'Id',
 typeAhead: false,
 hideLabel: true,
 hideTrigger:true,
 anchor: '100%',
 listConfig: {
  loadingText: 'Searching...',
  emptyText: 'No matching posts found.',

  // Custom rendering template for each item
  getInnerTpl: function() {
    return '<h3>{Name}</h3>';
  }
 },
 pageSize: 10
}

The underlying Store used the SalesForce.com services proxy:

 Ext.define('MyApp.store.MyStore', {
  extend: 'Ext.data.Store',
  storeId: 'MyStore',
  idProperty: 'Id',
  fields: [ { name: 'Id' } , {name: 'Name'}, {name: 'BillingCity'}],
  proxy: {
    type: 'rest',
    url: '/services/proxy',
    headers: {
      'SalesforceProxy-Endpoint' :  serverURL + PATH,
      'Authorization': 'OAuth ' + SESSION_ID
    }
  }
 });

The serverUrl and session ID are dynamically output at runtime from SalesForce’s apex architecture:

<apex:page docType="html-5.0" sidebar="false" showHeader="false" 
    standardStylesheets="false" cache="true" applyBodyTag="false">
 
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    <script src="{!URLFOR($Resource.ExtJS,'ext-all.js')}"></script>
    <link rel="stylesheet" href="{!URLFOR($Resource.ExtJS,'ext-theme-neptune-all.css')}"/>
    <script type="text/javascript">
      var SESSION_ID = '{!$Api.Session_ID}';
      var serverURL = '{!SUBSTITUTE(SUBSTITUTE(LEFT($Api.Partner_Server_URL_210, FIND( '/services', $Api.Partner_Server_URL_260)), 'visual.force', 'salesforce'), 'c.', '')}';
      // If its a mydomain enabled org, the mydomain name needs to be stripped 
      var splitURL = serverURL.split(/\./g);
      if(splitURL.length==4) {
          splitURL[0] = 'https://';
          serverURL = splitURL.join(".").replace('.','');
      }
     
      var PATH = 'services/apexrest/XN/Account';
   </script>

Using Sencha.io Src in your Touch Apps

before

Sencha.io Src is a nifty little anonymous cloud service available from Sencha Inc. that will automatically scale images for a mobile devices. This is particularly handy if you’re trying to dynamically adapt markup that had been produced for desktop web to a mobile device.

Recently we developed a Sencha-based app for the Archdiocese of St. Louis. One of the functions of this app was to display news articles from http://stlouisreview.com/. Content is delivered to the device from a JSON data feed, however as illustrated below, none of the images were sized appropriately for mobile devices – resulting in a blown-out layout.

Our solution was to simply modify our Sencha Touch container’s display template to dynamically redirect the header image to Sencha io.src as illustrated below. Note that the project was developed using Sencha Architect, thereby necessitating use of an override:

Ext.define('ArchSTL.view.override.news.Detail', {
    override: 'ArchSTL.view.news.Detail',
    config: {
      tpl: Ext.create('Ext.XTemplate',
       '{[this.senchifyUrl(values.description)]}', {

        senchifyUrl: function(str) {

            // match src="url"
            var urls = str.match(/src=(.+?[\.jpg|\.gif|\.png]')/);

            // get width of viewport
            var width = Ext.Viewport.element.getWidth() - 50;
         
            if (urls != null) {
              var url = urls[0].slice(5,-1);
              str = str.replace(url,"http://src.sencha.io/" + width + "/" + url);
            }
      
            return str;
        }
      })
    }
});

after
This change to the template worked great, as illustrated by the final result:

You can learn more about Sencha io.src here:
http://docs.sencha.io/current/index.html#!/guide/src

Check it out!

Get Figgy with It! (Fig Leaf Software is Hiring!)

My company, Fig Leaf Software, has several open positions. Join a great team and engineer awesome solutions!

Other benefits include, but are not limited to:

  • Generous paid vacation
  • BC/BS PPO Health insurance
  • Optional dental / vision coverage
  • Medical Flex spending account
  • 401K with a % of company matching
  • Tuition reimbursement
  • Access to certified training and continuing education
  • Parking / Metrocheck allowance

We’re looking for:

  • Google Sales Engineer / Search Specialist
    Do you like working closely with sales and technical teams to drive business?  If so, and you have experience with Google Enterprise products (Search, Maps, Apps), we invite you to learn more about our Google SE position.
    Would you like to know more?
  • Sencha Developer / Evangelist
    Work directly with the company’s founder, Steve Drucker, to help us grow and service our expanding Sencha Ext JS and Sencha Touch consulting practice! Build awesome web apps for desktop and mobile!
  • Drupal Developer
    Create awesome content-managed websites for large public/private orgs with Drupal. Develop custom Drupal modules. Amaze your friends!
  • Proposal Manager
    Work directly with Fig Leaf’s management team to prepare competitive proposals in compliance with client requirements and technical specifications. Spec out the next generation of web solutions that use the latest technologies!

Other open positions include:

  • Technical Project Manager
  • Tech Support Manager
  • Account Manager-Sales Rep
  • Content Manager
  • Middleware developers (PHP, ColdFusion, Java, .NET)

These positions are local to the Washington DC-Metro area.

So what are you waiting for? Send your resume to jobs@figleaf.com!

Adobe LiveCycle FormCalc Example – Calculating Business Days

Recently I taught an Adobe Livecycle forms course where one of the students asked me to cobble together some FormCalc code that would calculate X business days from a user-entered date.

This was the result:

var startdate = Date2Num($,"YYYY-MM-DD");
var bizdays = 10;
var modifier = 0;

// figure out modifier
for i=1 upto bizdays step 1 do
 var day = Date2Num($,"YYYY-MM-DD") + i;
 var dayOfWeek = Num2Date(day,"EEE");
 if (dayOfWeek == "Sat" or dayOfWeek == "Sun") then
   modifier = modifier + 1;
 endif
endfor

var enddate =  Date2Num($,"YYYY-MM-DD") +  bizdays + modifier;

Date2 = Num2Date(enddate,"YYYY-MM-DD");