Node, HTML, JavaScript and Hackathons

hackathon starter project

 

These days creating a new piece of web or mobile software feels a lot like combining already made pieces together. Adding some glue so they do not fall apart, releasing version v1 and repeat the loop many times. Until you are satisfied that nobody cares or that you have actually built something useful.

Agile, lean and other tech product methodologies have thought us to use this process. And ever increasing modular nature of web and back end frameworks make it easy to follow these steps. Many hours are already spent by community of smart people while creating all the reusable modules for your future app.

Good example to illustrate this trend is Hackathon Starter project. Its created for people building web and mobile apps with help of Node.js. As the name suggests it was created as reusable prototype for hackathon projects. In hackathons you usually have ~24 hours to create a somewhat working project. As this template is beefed up with main modules it will save lots of time and will let you concentrate on the specific functionality you want to achieve.

OAuth, user management, payments, middleware for for rendering Twitter Bootstrap front end and many other packages are all built in.

This project has accumulated many development hours from open source community. It has main components for any basic web app or mobile app back end. And Node.js itself has a very active repository with modules for adding more complex functionality.

Such trend is fast accelerating the actual software development process and allows even more automation to it. All the external modules can be managed by maintaining project dependency settings and uploaded during build time. It also means that smaller teams can manage quite large software projects.

Welcome to the world of fast moving modular technology creation. As techie you have to adopt or become less and less productive as time goes by.

Would be great to hear your thoughts on this. Or if you have some story to share get in touch and we can glue together a blog post.

Read More >
Great OAuth tutorials for HTML5 applications

OAuth APIs and HTML5

Applications we build are more and more dependent on 3rd party data sources. And as Internet of things continues to grow, this fact becomes even more stronger.

It allows us to create great experiences for the app end users by presenting them data gathered from across the Internets. But at the same time we have to spend more time ensuring that our applications are consuming all this data securely and they only get access to the data they need. OAuth protocol was designed and developed for this exact reason.

While I was doing research on the best OAuth practices for HTML5 applications I came across several great online posts and tutorials which I want to share with HTMLCenter readers. I’m sure this will help someone who is looking to take greater control of OAuth authorization flow happening in HTML5 apps.

Let us know if we missed any good tutorials on this subject.

OAuth and JavaScript

JavaScript tutorial for creating authorisation flow with the most used social cloud services: Facebook, Google and Twitter. This tutorial covers the actual code you will need for creating JavaScript OAuth flow and what are the main differences between these 3 most popular social identity providers (once it comes to OAuth). All source code is also provided as a dowloadable file.

Flickr, OAuth and App Garden

Flickr is very well known online community for photographers. As well as hosting millions of great photo images this site has exposed several API resources for 3rd party applications to consume.

Majority of these API’s do require authorisation and its achieved by implementing OAuth flow. Flickr supports OAuth flows for Web, mobile and desktop apps and their team has created several tutorials on how to implement such authorisation flows. This tutorial is about OAuth 1.1 protocol.

Vimeo API and OAuth

Vimeo is another great online community. They are all about high quality videos. In order to allow programmable access to the user groups, videos, channels and albums Vimeo has several advanced API’s. They are implementing OAuth 1.0 protocol for authorization and this guide / tutorial covers the example flow as well as several libraries Vimeo tech team created for this purpose.

OAuth.io and multiple authorizations

OAuth.io is a bit different from others in this list.

Its a background API service which handles all the complexity of OAuth authorisations on behalf of client apps and exposes very simple JavaScript API for applications to use.

The OAuth tutorial they created goes through JavaScript APIs for integrating multiple cloud services at once. OAuth.io guys have also created a PhoneGap plugin and open sourced the core engine which drives their project as oauthd.

OAuth with PhoneGap applications

PhoneGap is a very popular hybrid framework for mobile developers. It allows to create HTML5 apps and then wrap them up in to the native mobile applications.

Of course many such mobile applications use OAuth protocol to consume cloud services and this tutorial covers OAuth authorization how to while working with PhoneGap framework. It goes through example Google API integration.

OAuth Sign-in with Kinvey

Kinvey is the backend as service cloud platform. Variety of mobile apps are using it for storing data, push notifications and analytics. If you are planning on using this platform for your mobile applications and it happens to be HTML5 apps, folks at Kinvey have created a very informative tutorial on how to implement this. Tutorial covers the concept of HTML5 and OAuth working together.

Usergrid and HTML5 OAuth

Usergrid is an open source data platform for mobile applications. Its being incubated by Apache foundation and is gaining the traction among mobile app developers as cloud based backend solution.

Apigee, the company behind Usergrid published good few tutorials related to the OAuth authorization flow for consuming resources exposed by Usergrid. This one is for applications powered by HTML5 and jQuery.

HTML5 local storage for OAuth tokens

And to finally one short tutorial about using HTML5 local storage API to store OAuth authorization tokens received by applications during the OAuth flow.

One warning though, local storage is useful for storing application data for persistence but security has to be considered as HTML5 local storage is handled by the web browser and can be accessed by other applications which have access to browsers local data.

Read More >
Building AngularJS based native mobile application. Part 2

This is the second part of tutorial for building native mobile application based on AngularJS, HTML5 markup and CSS styles. In the first part you will find how to setup the new project, add routes, controllers, HTML5 views and do simple testing in a standard web browser.

What we are doing in this tutorial?

In this tutorial part we are going to take previously created application and add back navigation button, sliding animations between the views and functionality to retrieve data from web services by using asynchronous HTTP communication. Finally I’ll give some hints how to wrap this application into PhoneGap framework in order to create installable version. Lets get started.

Providing navigation buttons

Adding back button to AngularJS framework

Last time we noticed that it would be great to have navigation options for app users so they can return to the previously viewed application page.
As our example application is quite simple, adding HTML markup for navigation is a straight forward process. Ratchet (the front end framework we are using for this project) has back button styles already built in. We just have to add a link element above the title of navigation bar to TheatersControllerView.html. Adding it below would create right side navigation bar button.

<header>
  <a href="#/">Back</a>
  <h1>Find a theater</h1>
</header>

The back route we add is to the root view as there is only way app user can navigate to TheatersControllerView. Other views in our app don’t need to have navigation back option.

Adding animations to AngulaJS projects

From the version 1.1.5 AngularJS framework has inbuilt support for animated transitions for certain directives. This currently can be done in 3 ways, CSS Transitions, CSS Animations and good old JavaScript way. There is even website dedicated solely to AngularJS animations and it does a good job explaining how stuff works (this is why a great developer community supporting the framework is so useful).
We are going to use CSS Transition in this tutorial by adding ng-animate element to our HTML to let AngulaJS know we want to have CSS style animated transition. We have to provide this element with the value of our CSS animation name. While building HTML AngularJS will attach 2 CSS classes to the DOM element named according to the animation name we gave earlier. Given that our animation name is slide the classes added by AngularJS will be slide-enter and slide-enter-active. Its possible to provide custom names for CSS classes as well. You would do it like this

ng-animate="{enter: 'slide-begin', leave: 'slide-exit'}"

Lets add simple CSS class code and ng-animate element to our projects index.html root file after which the file content should look like this

<!DOCTYPE html>
<html data-ng-app="pomidoroApp">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="stylesheet" href="css/ratchet.css">
    <link rel="stylesheet" href="css/app.css">
  </head>
  <body>
    <style type="text/css">
      /* Angular.js animated navigation */
      .slide-enter,
      .slide-leave
      {
        -webkit-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        -moz-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        -ms-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        -o-transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
        transition: 300ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
      }  
      .slide-enter {
        left: 100%;
      }
      .slide-enter.slide-enter-active {
        left: 0px;
      }      
      .slide-leave {}
      .slide-leave.slide-leave-active{
      left: -200px;
      }
    </style>
    <!-- placeholder for view markup -->
    <div ng-view ng-animate="'slide'"></div>  
    <script src="js/angular.min.js"></script>
    <script src="js/app.js"></script>
  </body>
</html>

Now after testing the project code in Safari browser we can see a nice navigation effect after the particular movie from the list is clicked by user. This animation transitions us to the theaters controller and view. After testing on mobile devices I noticed that sliding effect is a little bit slow and has small lag as well. How to smooth it up is not the goal of this tutorial and most likely I’ll cover this subject in the separate post here on HTML Center. Next chapter is about adding web services communication functionality to consume Rotten Tomatoes API data and display it in our app.

Adding HTTP communication to AngularJS app

Building mobile application with Rotten Tomatoes API

For performing HTTP requests AngularJS has a property named $http (nice and simple naming). It also has strong support for promises. Promises (if you are not so much familiar with them) is a concept we use while dealing with async communication requests. Then we perform request and assign result of that request to some variable but do not expect it to have complete response right away. Because communication with 3rd party web service takes time. Therefore promise variables are guaranteed to have response data some time in the future.

In the previous tutorial part I have mentioned that we will be using Rotten Tomatoes API for retrieving movie data. Their API for developers is both simple and provides useful movie data. Simply go and register your own developer account with them to receive API key. It’s quite a straight forward process. Once you have API credentials the simple query to Rotten Tomatoes web service in order to get 5 hot movies currently shown in UK theaters is performed like HTTP Get request with the following string

http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=5&page=1&country=uk&apikey=YOUR.API.KEY

It is a good information security practice not to store your sensitive developer credentials data in app itself. As all applications are running on devices which you have completely no control off. Always try to perform communication with 3rd party API’s via back end code and keep mobile application as a simple client.

This approach will also help while dealing with Cross Origin Resource Sharing issues as JavaScript and Ajax HTTP communication needs extra attention to stay secure. On your backed you can configure CORS settings for specific requests origins etc. I have prepared very simple php based backed file which will only make a request to Rotten Tomatoes API and return all result data back to our mobile app

<?php

// Simple tweak to allow access from any origin
// Credits to http://stackoverflow.com/questions/8719276/cors-with-php-headers
//
if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");         

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}

///////////////////////////////////////
// SETUP //////////////////////////////
///////////////////////////////////////

// API credentials
//
$apikey = "YOUR ROTTEN TOMATOES API KEY";

// Number of items in response 
$returnitems = 5;

$url = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=".$returnitems."&page=1&country=uk&apikey=".$apikey;

// Building string for GET request
//
$requeststr = $url;

// CURL for communicating with web service
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$requeststr);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

$response = curl_exec($ch);
echo $response;
?>

You will notice at the beginning of the file I have code to enable cross domain access for Ajax requests. You can limit this to specific origin, domain etc.

We will now update our factory and replace static and hard coded data we previously had with the $http.get request. $http is the service available to your applications if it uses AngularJS framework and is in detail described in official documentation.  As we already discussed all HTTP communication is asynchronous and this means we have to handle the scenario where requested data is not right away available for our controller and the view. We add the following code to the factory method to recommendedMoviesFactory

// This is the place for performing http communication
// with 3rd party web services.
var url = 'your.backend.url'

return $http.get(url).then( function(response){
  return response.data;
})

Now in the RootControler we are handling the fact that data coming from $http can be delayed by adding ready flag to the $scope element. This will let us display HTML elements in the view only once all the data is received from Rotten Tomatoes API

// RootController
//
pomidoroApp.controller('RootController', function($scope,recommendedMoviesFactory){

    // Controller is going to set recommendedMovies
    // variable for the $scope object in order for view to
    // display its contents on the screen as html 
    $scope.recommendedMovies = [];

    // Just a housekeeping.
    // In the init method we are declaring all the
    // neccesarry settings and assignments
    init();

    function init(){

        // As we need to wait for $http.get 
        // request data to be ready we are 
        // using .then on the promisse received
        // from factory
        recommendedMoviesFactory.getRecommended().then(function(data) {
           //this will execute when the 
           //AJAX call completes.
           $scope.recommendedMovies = data.movies;
           $scope.ready = true;           
           console.log(data.movies);
        });
    };

});

Whats left is to update the RootControlerView with the the information about new elements in the data provided by controller (notice in previous code example, I’m using console.log() to print out and investigate all the available JSON data structure supplied by Rotten Tomatoes API) and add a filter in order to filter list of 5 movies with the search input field. Here is the updated version of this file

<div>
  <ul>
    <li>Recommended movies</li>
    <li ng-show="!ready">
      Receiving data...
    </li>
    <li ng-show="ready" ng-repeat="movie in recommendedMovies | filter:name">
      <a href="#/theaters">
        <div>
         <img style="float:left; width:120px; height:177px; margin-right:10px;"class="movieimg" src="{{movie.posters.profile}}" />
         <strong style="font-size:18px;">{{movie.title}}</strong>
         <p style="font-size:16px;">{{movie.critics_consensus}}</p>
        </div>
        <div style="clear:both;"></div>   
      </a>
    </li>
  </ul>
</div>

In the above code I’m making use of ready variable which is being set in controller and will be set to yes once all requested movie data is available. Until then I’m going to display "Receiving data..." text in the list item element. ng-show is the directive making this all happen as I only have to supply ng-show="!ready" and AngularJS knows to hide it once variable is being set to true.

Now once project files are updated, reloading the page will give us the following result. By no means its a finished mobile application but it has a good foundations and MVC framework to build on to. But it has scroll view, dynamically loading content from external web services, animated transitions and is powered by AngularJS.

Building mobile application with AngularJS

Testing AngularJS project with PhoneGap

As we were working in the directory called www migrating this project to wraper like PhoneGap and make it installable app is quite easy. You just have to replace contents of the www directory in your PhoneGap XCode project with the ones you created during this tutorial. If you want to understand how to create PhoneGap powered XCode application we have good tutorial for your here at HTML Center.

I hope you have enjoyed this tutorial, final source code for example application can be found hosted on the GitHub. As always I welcome all the comments, suggestions and advice.

Read More >
How to build AngularJS based native mobile application

This is the first part of the tutorial for building native mobile application based on AngularJS framework, HTML5 markup and CSS styles. The second tutorial part can be found by following the link.

I have recently started using AngularJS a JavaScript tool set for building HTML5 applications. As we are covering cross platform mobile application development here on htmlcenter, I decided to write a tutorial and share my experiences while using powerful and quite easy to understand AngularJS MVC structure for developing cross platform mobile applications.

This tutorial is about how to build Angular powered HTML5 mobile application, wrap it up with PhoneGap and distribute as a native mobile app (on several mobile platforms if you wish so). We have split tutorial into 2 parts, just to make it easier for information to sink in. As always, links to the example source code can be found at the end of the tutorial posts.

What we are going to cover?

First, we will briefly explore what is AngularJS (however, this tutorial is not about learning the basics),  we are going to pick Ratchet as a front end framework for our HTML5 mobile application and create MVC structure. Second tutorial part covers how to make our view transitions animated, how AngularJS communicates with web services  and how to wrap up AngularJS application with PhoneGap. Sounds like we have some ground to cover. Lets get started.

Why AngularJS?

AngularJS is a tool set for developing HTML5 applications. Its has alternatives like Backbone and EmberJS (and the bunch of others). My reason for picking AngularJS among others was rapidly growing developer community around this framework and resource support provided to it by Google. Any framework needs at least these 2 elements (passionate community and leading tech company support) to be successful.

As I have mentioned before, we are not going to cover the very basics of AngularJS in this tutorial, they have relatively good getting started guides, tutorials and videos online. One particularly good video for starting beginning AngularJS is created by Dan Wahlin. Having said that, I tried my best to comment and explain the sample code created during this tutorial.

Selecting Ratchet

Ratchet and AngularJS development

Ratchet is a collection of iOS-ish looking HTML5 components. Guys did a good job creating and styling HTML elements which look quite similar to native iOS ones. And you can always tweak them to suit application design by only changing CSS properties. For our purpose we will not be using any JavaScript files supplied by Ratchet as we are going to create our own.

Go ahead and download the latest version of Ratchet. Once downloaded, create a separate new directory with the name www and copy only the files we are going to need in the future steps. These are index.html and style .css files. My new directory looks as below. Other nested directories in this project are for organizing JavaScript files, images and HTML code for our application views. For now just create an empty directories with these names

Folder structure for AngularJS mobile application

Getting Angular and naming the project

Go ahead, download latest AngularJS file and place it in js directory. In the example project I’m using minimized version angular.min.js.
Now, before starting to write any code we have to decide on what our example application will be, how will we name it and how many views we want to have.

I’m not a big movie watcher but once I decide to watch one – Rotten Tomatoes is the place I go to find useful reviews about the film. And they have an API for sharing data. Our app can show 5 great movies to watch. Sounds like a good idea for example project.
We are going to call it Pomidoro (European version of tomato). As for application views we will have 3 of them. First view is going to be the main view displaying 5 suggested movies in the list. Second view will show details of the Theaters this specific movie is currently on shown and the third view will be settings area for application user to change. We will have tab bar controller for navigating between the views. And we want transition between the views to be animated, to mimic actual native mobile app behavior. All the testing and debugging will be performed in Chrome web browser.

HTML and JavaScript code for Pomidoro mobile app

Looking at index.html file which we copied from Ratchet we see that it needs some changes. First we have to remove all the references to ratchet.js as this is no use for our project. Next we have to make sure all the paths to style files and images are actually matching our directory structure. Here is what I have after these changes are made

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="stylesheet" href="css/ratchet.css">
    <link rel="stylesheet" href="css/app.css">
  </head>
  <body>
  <header>
    <h1>Pomidoro App</h1>
  </header>
  <nav>
    <form>
      <input type="search" placeholder="Search">
    </form>
  </nav>
  <nav>
    <ul>
      <li>
        <a href="#">
          <img src="img/icon-home.png">
          <div>Movies</div>
        </a>
      </li>
      <li>
        <a href="#">
          <img src="img/icon-profile.png">
          <div>Theaters</div>
        </a>
      </li>
      <li>
        <a href="#">
          <img src="img/icon-settings.png">
          <div>Settings</div>
        </a>
      </li>
    </ul>
  </nav>

  <div>
    <ul>
      <li>Recommended movies</li>
      <!-- repeat this for all 5 movies in the list -->
      <li>
        <a href="#">
          <div><img src="img/argo.png"></div>
          <strong>Movie Name</strong><br />
          <p>Some sort of movie description</p>
        </a>
      </li>
    </ul>
  </div>

<script src="js/angular.min.js">
<script src="js/app.js"></script>

  </body>
</html>

In this HTML file we are referencing styles and AngularJS toolkit. The main JavaScript code for our application will go to app.js. I have only one movie listed in the unordered list because we will use AngularJS to do the magic for us while populating all of them. Our movie will have image url, movie name and movie description as parameters.
Now, taking a look at app.js. First we are going do is to create AngularJS application module and call it by our application name

var pomidoroApp = angular.module('pomidoroApp',[]);

Once we have the module created we can start adding routes with controllers and views to it. If you have some MVC (module, view, controller) structure experience you are going to like AngularJS right away. It truly complies to this structure and it allows developers to keep their data, app logic and any partial code (like views) separate and well organized. As we have previously decided, there will be 3 routes, which means 3 separate controllers with 3 separate views. Lets add them to the app.js file. I’m also adding 2 factories for holding hard coded movie data (for now). Completed code for this file is below. I have commented it section by section so its easier to understand

// Defining angular application model
// for Pomidoro app
//
var pomidoroApp = angular.module('pomidoroApp',[]);

////////// ROUTING /////////////////////////
// Deffining $routeProvider for Pomidoro applicatiom module
//
pomidoroApp.config(function ($routeProvider) {
    $routeProvider

        // We are going to define routes,
        // controllers and templates associated
        // with these routes.
        // You can change these but make sure
        // you know what you are doing
        //

        // main route
        //
        .when('/',
        {
            controller: 'RootController',
            templateUrl: 'views/RootControllerView.html'

        })

        // theaters list page
        //
        .when('/theaters',
        {
            controller: 'TheatersController',
            templateUrl: 'views/TheatersControllerView.html'

        })

        // settings page
        //
        .when('/settings',
        {
            controller: 'SettingsController',
            templateUrl: 'views/SettingsControllerView.html'

        })

        // if non of the above routes
        // are matched we are setting router
        // to redirect to the RootController
        .otherwise({ redirectTo: '/'});
});

///////// CONTROLERS ////////////////////////////
// Below we are going to define all the controllers
// we have defined in the router
//

// RootController
//
pomidoroApp.controller('RootController', function($scope,recommendedMoviesFactory){

    // Controller is going to set recommendedMovies
    // variable for the $scope object in order for view to
    // display its contents on the screen as html 
    $scope.recommendedMovies = [];

    // Just a housekeeping.
    // In the init method we are declaring all the
    // neccesarry settings and assignments
    init();

    function init(){
        $scope.recommendedMovies = recommendedMoviesFactory.getRecommended();
    }    
});

// TheatersController
//
pomidoroApp.controller('TheatersController', function($scope,theatersFactory){

    // This controller is going to set theaters
    // variable for the $scope object in order for view to
    // display its contents on the screen as html 
    $scope.theaters = [];

    // Just a housekeeping.
    // In the init method we are declaring all the
    // neccesarry settings and assignments
    init();

    function init(){
        $scope.theaters = theatersFactory.getTheaters();
    }    
});

// SettingsController
//
pomidoroApp.controller('SettingsController', function($scope){
    // This controller is going just to serve the view
});
///////////// FACTORIES ////////////////////////////

// Defining recommendedMovies factory
// It has 5 recommended movies and 
// makes them available to controller
// so it can pass values to the template
//
pomidoroApp.factory('recommendedMoviesFactory', function(){
    var recommended = [
        { name: 'World War Z', description: 'The story revolves around United Nations employee Gerry Lane (Pitt), who traverses the world in a race against time to stop a pandemic', img: 'img/wardwarz.png'},
        { name: 'Star Trek Into Darkness', description: 'When the crew of the Enterprise is called back home, they find an unstoppable force of terror from within their own organization has detonated the fleet and everything it stands for', img: 'img/intodarkness.png'},
        { name: 'The Iceman', description: 'Appearing to be living the American dream as a devoted husband and father in reality Kuklinski was a ruthless killer-for-hire.', img: 'img/wardwarz.png'},
        { name: 'Iron Man 3', description: 'When Stark finds his personal world destroyed at his enemys hands, he embarks on a harrowing quest to find those responsible.', img: 'img/wardwarz.png'},
        { name: 'Django Unchained', description: 'Set in the South two years before the Civil War, Django Unchained stars Jamie Foxx as Django', img: 'img/wardwarz.png'}      
    ];

    var factory = {};
    factory.getRecommended = function(){

        // If performing http communication to receive
        // factory data, the best would be to put http
        // communication code here and return the results
        return recommended;
    }
    return factory;
});

// Defining theatersFactory factory
// In this example it has 5 movie theatres 
// but in real live application you would 
// want it to get this data from the web
// service, based on the the movie selected
// by user
//
pomidoroApp.factory('theatersFactory', function(){
    var theaters = [
        { name: 'Everyman Walton', address: '85-89 High Street London'},
        { name: 'Ambassador Cinemas', address: 'Peacocks Centre Woking'},
        { name: 'ODEON Kingston', address: 'larence Street Kingston Upon Thames'},
        { name: 'Curzon Richmond', address: '3 Water Lane Richmond'},
        { name: 'ODEON Studio Richmond', address: '6 Red Lion Street Richmond'}
    ];

    var factory = {};
    factory.getTheaters = function(){

        // If performing http communication to receive
        // factory data, the best would be to put http
        // communication code here and return the results
        return theaters;
    }

    return factory;
});

As a summary, we have just created 3 different routes (which means that once this specific url is requested by browser AngularJS will ask corresponding controller to serve specific view) and 3 controllers which are in charge of serving specific view elements stored in .html files and binding any data with these views.

We can now go back to our index.html file and cut out all the HTML markup leaving just a placeholder for HTML content which is going to be loaded from view files by AngularJS. For this to happen we will add directives to HTML element tags so AngularJS knows what do we want to achieve. Such approach makes our app a single page application (or SPA as developers like to call these type of apps). Here is the code of trimmed down index.html which now looks nice and tidy

<!DOCTYPE html>
<html data-ng-app="pomidoroApp">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="stylesheet" href="css/ratchet.css">
    <link rel="stylesheet" href="css/app.css">
  </head>
  <body>
    <!-- placeholder for view markup -->
    <div ng-view></div>

    <script src="js/angular.min.js"></script>
    <script src="js/app.js"></script>
  </body>
</html>

You will notice directives I have added to <html> and the <div> elements which now serves as placeholder for application content.
So what will happen now once / route is requested by the browser? The index.html file will be served and AngularJS will prefill <div ng-view> with contents served by our RootController. And from the app.js code we see that this controller is going to serve RootControllerView.html. What are the contents of this file?

<header>
  <h1>Pomidoro App</h1>
</header>
<nav>
  <form>
    <input type="search" placeholder="Search">
  </form>
</nav>
<nav>
  <ul>
    <li>
      <a href="/">
        <img src="img/icon-home.png">
        <div>Movies</div>
      </a>
    </li>
    <li>
      <a href="#/theaters">
        <img src="img/icon-profile.png">
        <div>Theaters</div>
      </a>
    </li>
    <li>
      <a href="#/settings">
        <img src="img/icon-settings.png">
        <div>Settings</div>
      </a>
    </li>
  </ul>
</nav>
<div>
  <ul>
    <li>Recommended movies</li>
    <li data-ng-repeat="movie in recommendedMovies">
      <a href="#/theaters">
        <div><img src="img/hollywoodcat.png"></div>
        <strong>{{movie.name}}</strong><br />
        <p>{{movie.description}}</p>
        <span></span>
      </a>
    </li>
  </ul>
</div>

Here we have our menu items, and the rest of HTML markup from the front page. Most interesting part is data-ng-repeat directive in <li> element. Its tells AngularJS to repeatedly print this element until some condition is met. In our case its as long as we have any elements in recommendedMovies data array (this is defined in controller). And for each element we are going to print out the name, description and picture (well, to make things a bit of fun I have added a lol cat as a visual representation of these movies. I’m sure you can do better in your apps..). I also have applied the same structure to theatersFactory controller and the view for displaying available theaters. Here is how our application now looks after the changes (tested in Chrome web browser).

Pomidoro AngularJS powered mobile application

Whats next?

Congratulations on reaching so for with this tutorial. You have created core for mobile HTML5 application powered by AngularJS. There are few bits still remaining though. We need to add animation between loading the views (to create experience mobile app users are used to), it would be nice to have back buttons on the top navigation bar in order for app user to navigate back to previous view. And we have a bunch of hardcoded data about movies, this can be retrieved through HTTP communication to RottenTomatoes API. I have covered these topics in the second part of this tutorial. Follow htmlcenter for the stream of similar tutorials. Today’s application code lives here. Have fun.

Read More >
Crossing platforms between iOS and Android. Extending PhoneGap project

One of the main reasons to use hybrid mobile application framework like PhoneGap for development is to maintain you project code base in one programming language, while deploying mobile applications across many mobile platforms. PhoneGap is the wrapper for HTML5 applications to make them run on multiple mobile operating systems as native apps. Applications are written in JavaScript and framework provides API’s to access native mobile device functionality. Developers can even write their own plugins to get any specific native OS functionality they want.

I have recently published 4 piece tutorial about developing PhoneGap based mobile application for Apple iOS platform. In the beginning of that tutorial I promised to use the same application JavaScript code for another mobile app which is created to run on Android powered mobile devices. This post is about doing exactly that. I will share my experience of taking PhoneGap application code from iOS based app and moving it over to the Android platform. Some native elements will have to be changed but we will talk about them once we get there. Now, lets do some work.

Creating a new PhoneGap project for Android

First we need to setup PhoneGap framework project for Android application. Detailed steps are listed on official documentation pages, they are much similar to creating new PhoneGap project for almost any mobile platform. You have to download PhoneGap framework, navigate to the lib directory, then to specific mobile OS you are developing for, locate the bin directory there and run a simple console one liner. For Android projects it is the following

 ./create <project_folder_path> <package_name> <project_name>

You have to replace the text with actual values of your project path, package name and project name. Once executed this script will create a fresh Android project with bare bones PhoneGap application in it.
This is the structure of just created Android application project

Building PhoneGap project for Android

If you followed the previous PhoneGap app building tutorial on HTMLCenter you will recognize www directory where all HTML5, CSS and JavaScript files live. If not, www folder is where all your HTML5 application files must be located. Next, in libs directory we see cordova archive being used in the project for providing binding between JavaSript API’s and native Java code in the application. Rest of the project structure is a typical Android mobile application project. By looking at main YummyThings.java class we can see that start url is being served from configurations file which is located in xml directory in the project tree. Default start url for PgoneGap script generated new projects is www/index.html

Migrating PhoneGap application from iOS to Android

We now want to replace contents of www directory with the source files of HTML5 application we have already made earlier.
Have you noticed that files in this directory are similar in both projects, even if one of them is for iOS devices and another one is for Android? This is main power of hybrid mobile app frameworks like PhoneGap. You can keep the same HTML5 code base on all your projects with some minor platform specific tweaks.

After replacing the files I’m going to do some changes to the code of previous app, mainly removing JavaScript code related to the native navigation bar we had in earlier project. And this is a good chance to do a little bit of general refactoring to make my code more readable. Here is the final structure of www directory for this PhoneGap powered Android project

PgoneGap application structure for Android mobile

Lets take a look at the main files.
We have index.html which as we checked earlier is our entry point file and will be loaded first by default. In this file I have simple HTML5 element structure, import of CSS styles and import of JavaScript files. In my PhoneGap applications I prefer to keep index.html file simple and clean. All application dynamic and functionality is performed in JavaScript files.
One important element here is the 'viewport' metatag. Viewports are the virtual borders used by browsers while displaying content. These settings can and will affect how HTML5 elements are displayed to the user and its important to get them right. You can read more on this subject in this well written article and for our project we have to make sure this meta tag has values

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />

Below is the full code for our index.html file

<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />

        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <script type="text/javascript" src="js/cordova-2.6.0.js"></script>
        <script type="text/javascript" src="js/jquery.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
        <script type="text/javascript" src="js/webService.js"></script>

        <title>Yummy Things</title>
    </head>

    <body onload="init()">

        <div id="locationplaceholder"></div> 

        <div id="menu">    
            <input id="question" type="text"></input>
            <div type="button" onclick="callWebService()">Find recipes</div>
            <div id="yummy"></div>
        </div>
    </body>
</html>

There are few JavaScript functions referenced here and actual files imported via <script> attribute. The main JavaScript file is index.js and it does the heavy work for our application. Function init() is defined in this file and it adds event listener for initial PhoneGap event 'deviceready'. Lets take a closer look to index.js contents

// Global variables
//
var onMobile = false;

// Declaring all jQeury bindings 
// once document is ready
//
$(document).ready( function(){

    // Once search button is clicked app
    // will show the 'content' element on the screen
    //
    $(".share").click(function (e) {
        $('.content').toggleClass('show');
    });
});

// First we are going to check if this PhoneGap app is running on
// supported mobile device (in our case it will be just iOS/Android)
//
function init(){
    if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android)/)) {
        onMobile = true;
        // If running on mobile device, we have to register
        // for 'deviceready' event before moving forward
        document.addEventListener("deviceready", appInit(), false);

        // Log
        //
        console.log('index.js: running on supported mobile device');
    } else {
        // Log
        //
        console.log('index.js: running in the browser');
        appInit();
    }
}

// Once Cordova is loaded we are going to perform all
// app start tasks and add funcionality to specific DOM events
//
var appInit = function () {
    // Log
    //
    console.log("index.js: appInit() runs..");

    // Getting the last used search keyword
    // and updating the input text field
    // If there is no value, means default
    // keyphrase will be used
    //
    var lastSearch = window.localStorage.getItem("searchTerm");

    // Log
    //
    console.log("index.js: lastSearch="+lastSearch);

    // Prefilling search field 
    if (lastSearch){
        $("#question").val(lastSearch);
    }else{
        $("#question").val('your ingridient?');
    }

    // Getting the location coordinates and 
    // location name
    //
    getLocationName();
}

// Geting location coordinates and updating HTML markup
// with received result
//
function getLocationName () {

    // Log
    //
    console.log("index.js: getting geolocation..");
    navigator.geolocation.getCurrentPosition(onSuccess, onError);

    // Success
    //
    function onSuccess(position) {

      // Capturing values for latitude + longitude
      //
      var latitude = position.coords.latitude;
      var longitude = position.coords.longitude;

      console.log('Received current location: ' + latitude + ',' + longitude);

      // Asking maps.googleapis for name of the city
      //
      var url = 'http://your apiurl.com/?latitude='+latitude+'&longitude='+longitude;

      $.get(url, function(data) {

        // Add results to HTML
        $("#locationplaceholder").html("<div id='location'>Your current location is:<br /><strong>"+data+"</strong><br />Choose food wisely!</div>");

        // Log received content
        console.log("Location = " + data);

      });

    }
    // Error
    //
    function onError(error) {

        console.log('Received geolocation error. code:' + error.code);
        console.log('Received geolocation error. code:' + error.message);

        // Leting user know if he has disabled 
        //
        if (error.code === 1){

            $("#locationplaceholder").html("<div id='location'>You have disabled acces to your current location. Check the app settings if you want YummyThings to know where you currently are!</div>");
        }
    }
}

First, after declaring global variables and binding jQuery events for DOM elements init() function is declared. It checks where this HTML5 application is running – on our supported mobile devices or not. If not, we presume application is running in the standard web browser (its very handy for debugging application in the browser!). If we run on mobile device we have to wait till 'deviceready' is triggered by PhoneGap before performing any API calls related to the framework.

Next we retrieve the last search parameter from local storage and pre filling search box for the user. We are also retrieving Geolocation coordinates and running quick query to Google Maps API to obtain location name based on longitude and latitude our app has. If user has disabled application access to the location data we will show him a notification.

Remaining JavaScript file webService.js performs a call to web service endpoint and updates HTML5 element with received data based on whats happening on the application screen. The web service end point being called is our own url where a simple php file is hosted and acting as a demo API. We have created this file in one of the earlier tutorials here on HTMLCenter and I’m including it with the source files for this tutorial as well.

Once compiled and installed onto device here is how Yummy application looks on Android powered phone

Porting PhoneGap project to Android

From the look and feel point of view its similar to our previous iOS version of Yummy Things application but remember its HTML5, CSS and JavaScript so with a little bit of these skills you can make application look as nice as you want.

Remaining bits and pieces

We will also need to change default Cordova application icon in /res directory within the project. There are different dimensions required for different screen resolutions. More detailed explanation is given in official Google Android developer guide. The same goes to splash screen. In order to add one to the PhoneGap Android project we have to make sure that config.xml file has the following plugin declared (by default it has)

<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>

We then go to main YummyThings.java file and add the following lines in main onCreate() method to actually set the splash screen to be displayed for specific time frame

 
super.setIntegerProperty("splashscreen", R.drawable.splash);
super.loadUrl(Config.getStartUrl(), 5000);

This finishes migration of our example PhoneGap iOS project to Android platform. YummyThings example mobile application is now supported on both these platforms.

Conclusions and whats next?

Overall it was not very hard work to port over existing PhoneGap wraped HTML5 application to a different platform. In the real life application you probably would want to consider some specific UX element differences between platforms so application users are getting what they are used to while using their Android mobile apps.
Like menu items, navigation back and accessing application settings. All these are a little bit different for each mobile OS and to have really appealing mobile application you have to make it easy for users who are used to performing tasks in specific way.
But the core application functionality can be easily maintained within the single JavaScript code base.

As always I’m adding source code for today’s finished tutorial on GitHub. If you have any questions about the above code, leave them under this post, I’ll be happy to answer.

Read More >
Developing PhoneGap mobile project. Final part

This is the final tutorial part for developing simple PhoneGap based mobile application from the ground up. Earlier in tutorial parts one, two and three we took a closer look at what role PhoneGap hybrid mobile development framework plays in mobile development and how it works. We have created a new project and added several elements of functionality, similar to what most mobile applications out there would have – user interface, HTTP communication, data storage, native controls etc. In this final part I’m going to show you Geolocation API implementation, how to prepare and delay application splash screen and finalize everything with application icon. We’ll be working with the code from the last tutorial part (you can find at the bottom of tutorial part 3). Source code for overall finished PhoneGap application example (including today’s changes) can be found at the bottom of this post. Lets get started!

Geolocation in PhoneGap mobile applications

Geolocation API is there to provide your app with information on actual location of the device app is running on. In most cases its done in format of latitude and longitude. Location data is provided by mobile OS which is running on the device (it uses GPS and various network ID’s to crystallize this data).

As per PhoneGap documentation, there is no guarantee that Geolocation API will provide your app with the current location data and this is important information to consider then you are designing your app. There should always be a fallback scenario in your code in case device will not return Geolocation data.

How we are going to use the data? Well lets simply add a notification box over the recipes search field telling our app user where he currently is. Just to avoid disappointed app users who cannot buy the right ingredients in stores.. Jokes aside here is how we are going to implement it in our PhoneGap project.

navigator.geolocation.getCurrentPosition(onSuccess, onError);

Its the JavaScript API call to retrieve current mobile device position, where onSuccess and onError are the functions for handling success and error for this call. PhoneGap official documentation gives you detailed explanation. If successful this call will give us back the position object witch contains several device position related values like speed, latitude, longitude and others. We are going to use latitude and longitude to check on the name of our current location.

var latitude = position.coords.latitude;
var longitude = position.coords.longitude;

We need to translate these coordinates to the actual location name and maps.googleapis will help us to do that. As we already have php back end file serving us as communication service with 3rd party APIs (tutorial part 2) we are going to add few lines of code so it makes additional API call to maps.googleapis service which will give us back the name of location based on supplied coordinates.

// Building string for request
//
$requeststr = "http://maps.googleapis.com/maps/api/geocode/json?";

$requeststr=$requeststr."latlng=".$latitude.",".$longitude;
$requeststr=$requeststr."&sensor=true";

// CURL for communicating with web service
//
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$requeststr);
curl_setopt($ch, CURLOPT_VERBOSE, 1);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

$response = curl_exec($ch);

// We will do some heavy lifting on the server side
// parse JSON and send back already prepared html with
// only the elements we have to add to fields
//
$response_decoded = json_decode($response, true);

// Give back location name
//
echo $response_decoded['results']['0']['address_components']['3']['long_name'];

Now once we have back end service in place we are going to amend the main index.js file in our project so it performs jQuery http get request to the back end providing the retrieved device coordinates. After receiving response this code will also populate dedicated <div> element for displaying geo location name. Here is the JavaScript code I have added to the file, detailed explanations follow below

// To retrieve current city name
// based on current device location we 
// will use PhoneGap Geolocation API
// and some Google Map API's magic

// Handeling 2 possible outcomes - success and failature
//
navigator.geolocation.getCurrentPosition(onSuccess, onError);

function onSuccess(position) {

     // Capturing values for latitude + longitude
     //
     var latitude = position.coords.latitude;
     var longitude = position.coords.longitude;

     console.log('Received current location: ' + latitude + ',' + longitude);

     // Asking maps.googleapis for name of the city
     //
     var url = 'http://your.server.url/?latitude='+latitude+'&longitude='+longitude;

     $.get(url, function(data) {

       // Add results to HTML
       //
       $("#locationplaceholder").html("<div id='location'>Your current location is:<br /><strong>"+data+"</strong><br />Choose food wisely!</div>");

       // Log received content
       console.log("Location = " + data);

     });

}

// onError Callback receives a PositionError object
//
function onError(error) {
   console.log('Received geolocation error. code:' + error.code);
   console.log('Received geolocation error. code:' + error.message);
}

Above code is already commented out (Its a good habit to spend some time to comment what your code is doing. saves time in the long run). We first retrieve coordinates through PhoneGap API, next performing http get request to selected back end server (replace this url with the one of your server containing back end php script). On successful response we update <div id="locationplaceholder"> element in the main index.html interface file. If we fail to retrieve position coordinates from the device onError function just logs error to the console. You can perform more advanced actions in this place if needed. After launching application now we can see the our current location.

PhoneGap geo location api implementation

Adding Splash screen in PhoneGap mobile projects

Once application is launched in most cases the first initial screen your users will see will be splash screen. As developer you can enable or disable this screen in your projects. Sometimes you will need it to be displayed for a longer then default time frame. In PhoneGap projects Splash screen is shown by default so you just have to replace default image files in Resources/splash project directory.

navigator.splashscreen.hide();
navigator.splashscreen.show();

And a little trick for keeping Splash screen on a screen a little longer (you will have to set AutoHideSplashScreen option in config.xml to false)

setTimeout(function() {
    navigator.splashscreen.hide();
}, 2000);

For our project I have just replaced default PhoneGap image to the Yummy Things splash screen image. I have also replaced mobile application icon (for standard and retina displays) in Resources/icons project directory. These are the icons your users will see on their mobile home screens. Application icons are one of the main criteria for users to select application from app store. Make sure it stands out. As for Yummy Things I quickly created simple icon with Yum on it. Now once install on the simulator or iOS powered device our application has custom icon and splash screen.

Creating PhoneGap mobile application from scratch

 Developing and debugging PhoneGap projects

With this done we can call our example application done. I hope these bones can serve as a starting point for your own applications built using PhoneGap mobile app development framework. At PopularOwl I’m currently working on one PhoneGap based project which consumes data from WordPress powered eCommerce site. Its an interesting experience and I’m planning to share it with you in the one or two posts here on htmlcenter site soon. Stay tuned!

As a finishing note to these tutorial series I want to mention few things about PhoneGap project architecture and debugging.

Mobile apps developed with PhoneGap framework are not your standard web apps. Yes, they are using HTML5 markup, JavaScript and CSS for styling but the content lives mostly on users mobile device as applications have to be functional offline as well as online. This means there is no remote web server to serve your pages. And mobile device is not your friend once it comes to reproduce web server behavior. So what do we do in complex PhoneGap mobile apps? The architecture is usually to have only one entry html page and add / remove markup from it by using JavaScript. JavaScript also creates transition effects and routing management (what content gets loaded once user goes to specific pages).

Debugging PhoneGap projects is actually not so straight forward. As the project runs in webview you will not get much out of native mobile OS debugging tools. You can log events in console (I did it in our example application) but in order to insert break point, stop the code and find what values are set you will have to use some sort of remote debugging solution. Weinre can be your friend here and debug.phonegap.com had its installation running. The idea is to insert specific JavaScript code into your application which will send information to remote server and you can see it through separate web interface. Quite a painful process.

Another option is to architect your PhoneGap mobile application so it its runnable on any web browser. This way you can use browser inbuilt tools for debugging. By designing your application to run in standard web browsers I mean make its life not dependent on specific PhoneGap APIs. For example before accessing any not native JavaScript API make sure it is accessible

function showAlert {
   // Are we wraped with
   // PhoneGap or running
   // in the browser?
   //
   if (navigator.notification) {
     navigator.notification.alert(message, null, title, 'OK');
   } else {
     alert(title + ": " + message) : message);
   }
}

If you want to better understand PhoneGap application design I would strongly recommend video presentation by Christophe Coenraets.

Several other useful links to keep you going. Template frameworks for PhoneGap applications (allows you to dynamically load html markup and keep it organized in separate files) – Mustache.js, Underscore.js. For front end check out Ratchet  and TopCoat CSS frameworks.

Finally you can find the source code for mobile app we have created during 4 tutorial parts on GitHub. This is by no means completed application but it might (and I hope it will) give you some thoughts and push to create and publish your own PhoneGap based applications. As always comments, questions and suggestions are welcome.

Read More >
Developing PhoneGap mobile project. Part 3

In the part one and part two of this tutorial we have discussed what PhoneGap mobile application framework is, its key components and elements. We have created a new PhoneGap mobile app project for iOS platform and started adding code for most used mobile application components. First such functionality was a communication with remote web services and 3rd party API’s through HTTP protocol by using jQuery library. Our mobile application has got a minimalistic and nice looking design created by using HTML5 markup and CSS styling.

In this part of the tutorial we will be adding data storage functionality and native application controls. Yes, native iOS controls so our PhoneGap based mobile app has a native look and feel native to its users. Such possibility to add native elements to PhoneGap hybrid mobile applications is one of the biggest strengths of this framework.

I’m going to be working with the code from the last tutorial part (you can find it on the bottom of the previous tutorial page). And the link to completed source code of today’s tutorial can be found at the end of tutorial. Lets get started.

First we are going to write a code to store last keyword that was used for search on the mobile device and retrieve it (for refilling search text box) once user launches application next time.

What storage for PhoneGap projects?

Implementing storage in PhoneGap mobile applications

We have 2 main options available to us in order to store data while using PhoneGap framework. One is SQL Lite database another one is local storage / session storage.

SQL lite based storage is quite a powerful option allowing application developers to interface database with SQL language meaning that your application can perform advanced searches and various analytic on the data stored in the database. The syntax of creating and communicating with such database by using PhoneGap API is the following

var localDatabase = window.openDatabase(database_name, database_version, database_displayname, database_size);

In your code you provide database name, version, display name and size. After database is created / accessed you get back database object and do interaction with it via db.transaction() method. For more information about SLQ lite implementation in PhoneGap projects check the documentation page.

Another method of storing data is local (session) storage. Its much simpler and is usually used to keep small amounts of data between application launches. Local storage in HTML5 world is the way to store data locally within the browser filesystem. This replaces storing data in cookies as faster and more secure approach. You do use key value pairs to store the data. Example implementation in PhoneGap app would be

window.localStorage.setItem("key", "value");

Session storage is similar to the local storage but data gets cleared after each browser session (once browser stops running).
For our application we are going to use local storage option and will save the last search keyword provided by user in order to populate search field next time our application is started. This data will be kept available for us in between application launches (after app is fully stopped by user). First we have to update our callWebService() function with the code to retrieve search term and store it locally

// Storing value in the local storage
var searchTerm = $("#question").val();
window.localStorage.setItem("searchTerm", searchTerm);
var question = window.localStorage.getItem("searchTerm");

And now once we have this value stored our application can ask jQuery to update search text input field on application start.

// Getting last used search keyword and updating input text field
var lastSearch = window.localStorage.getItem("searchTerm");
$("#question").val(lastSearch);

Our application will pre populate the last search keyword used by user in the text field with id="question" to remind application user what item he / she searched for the last time they viewed this page. I’m sure you can think of many more applications for such storing user data via PhoneGap storage APIs. Note that if you don’t want to keep locally stored data after application is closed use window.sessionStorage instead. Full source code of my main index.html file after changes are made

<!DOCTYPE html>
<!--
YummyThings app
index.html

Created by Saul Zukauskas @sauliuz
PopularOwl Labs // www.popularowl.com
@16.04.2013
-->
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <title></title>
        <script type="text/javascript" src="js/cordova-2.6.0.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
        <script type="text/javascript" src="js/jquery.js"></script>
   </head>
   <body>

        <script type="text/javascript">
            $( document ).ready(function() {

                // Getting the last used search keyword
                // and updating the input text field
                var lastSearch = window.localStorage.getItem("searchTerm");
                $("#question").val(lastSearch);

                // Once share class button clicked we will
                // show content class element on the screen
                $(".share").click(function (e) {
                  $('.content').toggleClass('show');

                  e.preventDefault();
                });
            });
        </script>        
        <script type="text/javascript" charset="utf-8">

            function callWebService(){

                // We don't want API call to be made everytime
                // button is clicked. Only if no data loaded or
                // search keyword has changed
                if ($('#yummy').is(':empty') || window.localStorage.getItem("searchTerm") !== $("#question").val()){

                    // Adding spinner image until we will get response
                    $("#yummy").append("<img class='spinner' src='img/loadinfo.net.gif' />");

                    // Storing value in the local storage
                    var searchTerm = $("#question").val();
                    window.localStorage.setItem("searchTerm", searchTerm);

                    var question = window.localStorage.getItem("searchTerm");

                    // Log
                    console.log("Question value from textfield: " + question);

                    //create the request url
                    var url = "http://your.test.server.url/?q=" + question + "&requirePictures=true";

                    // Log
                    console.log("Request string: " + url);

                    // Call to web server
                    $.get(url, function(data) {

                                    // Clear spinner
                                    $("#yummy").empty();

                                    // Add results to HTML
                                    $("#yummy").html(data);

                                    // Log received content
                                    console.log("Received string: " + data);

                                }
                          );                               
                } // end if
           }//end of method
         </script>

        <div id="menu">
            <input id="question" type="text"></input>
            <div type="button" onclick="callWebService()" id="webservice_call">Find recipes</div>
            <div id="yummy"></div>
        </div>
    </body>
</html>

How to use native controls in PhoneGap mobile applications?

By using PhoneGap local storage API we have started to actually interfere with the native elements of iOS (in our case this was data stored within the WebKit component). How PhoneGap does that? And how can we add some native controls like navigation bar on top of our view?

PhoneGap framework has 3 parts to it. Native core which is written in the native language for a specific mobile OS (Objective-C for iOS, Java for Android etc.). JavaScript API implementation file which exposes JavaScript functions to be used in the html files and maps these functions to a PhoneGap core. And a JavaScript code which you write in the mobile application html files (served from www directory) and which can use all the functions described in JavaScript API implementation. This is one of the key features which make PhoneGap hybrid application framework very powerful.

And the good news are – developers can extend PhoneGap core with custom plugins. This is done in the similar manner I have described above: implementing the needed functionality in the native code, creating a JavaScript file which maps native code with JavaScript functions and just using these functions in your code. And the beauty of open source is that developer community is always helpful and willing to share their knowledge. There are many of PhoneGap plugins already crated by PhoneGap and the developer community.

In our tutorial I will not make you code in Objective-C and we are going to use plugin which I wrote few weeks ago inspired by couple of other PhoneGap native iOS plugins out there. This plugin has 6 files and below are the instructions where to import them.

First 5 PhoneGap plugin files go to our projects plugins directory

Developing PhoneGap plugins

Remaining NavigationBar.js file goes into our projects main js folder. You can find and download all above plugin files from the GitHub repository.

After all files are imported into the project whats left is to add JavaScript code to our main index.js file for setting up navigation bar

// Will load Cordova iOS plugin
// to get native navigation bar

var navBar = cordova.require("cordova/plugin/iOSNavigationBar");
navBar.init();

// Create Navigation Bar with style
navBar.create("BlackOpaque");

Now once we have navigation bar in place I have added about.html file and created a function to display about page once about button is clicked on the navigation bar. We have to also manage the title of nav bar based on which page is being displayed and I created JavaScript code for this as well. After all the improvements our index.js code looks like this

// We have to add event listeners to capture main events
// Cordova framework sends us.
document.addEventListener("deviceready", onDeviceReady, false);

//////////////////////////////////////////////////////////
// Functions                                            //
//////////////////////////////////////////////////////////

function onDeviceReady() {
    // Log
    console.log('Received Event: deviceready');

    // Navigation management
    //window.sessionStorage.setItem("page", "index");
    var activePage = window.sessionStorage.getItem("page");

    console.log('Current page: ' + activePage);

    // We have to load custom Cordova iOS plugin
    // for native controls. Will be used to get custom navigation bar

    var navBar = cordova.require("cordova/plugin/iOSNavigationBar");
    navBar.init();

    // Create Navigation Bar with style
    navBar.create("BlackOpaque");

    switch(activePage) {
        case "index":
        navBar.setTitle("Yummy Things");
        break;
        case "about":
        navBar.setTitle("Yummy Things");
        break;
        default:
        navBar.setTitle("Yummy Things");
    }

    navBar.show();

    // Creating and managing
    // navigation buttons
    // Create right navigation button with a title

    switch(activePage) {
        case "index":
        navBar.setupRightButton("About","",onRightNavButtonClick);
        navBar.hideLeftButton();
        navBar.showRightButton();
        break;
        case "about":
        navBar.hideRightButton();
        navBar.setupLeftButton("Back","",onLeftNavButtonClick);
        navBar.showLeftButton();
        break;
        default:
        navBar.setupRightButton("About","",onRightNavButtonClick);
        navBar.hideLeftButton();
        navBar.showRightButton();
    }  

    // Navigation button actions
    // Right button
    function onRightNavButtonClick() {
        // navigation management
        window.sessionStorage.clear();
        window.sessionStorage.setItem("page", "about");
        window.location = "about.html";
        console.log('Performed onRightNavButtonClick' + activePage);
    }

    // Left button
    function onLeftNavButtonClick() {
        window.sessionStorage.clear();
        window.sessionStorage.setItem("page", "index");
        window.location = "index.html";
        // navigation management
        console.log('Performed onLeftNavButtonClick');
    }
}

There are additional functions in the code to handle button clicks and I’m using the session storage (remember, we just talked about it earlier) to keep the track on which page mobile application user currently is. After compiling and launching Yummy Things application in the simulator we have navigation bar and the about button in place. These are native controls, the same you get while developing mobile application natively.

Adding native navigation bar to PhoneGap applications

With this bit done we are now closing to the end of these tutorial series with only the last part left.

What’s Next?

You can progress to the last part of tutorial, where I’m implementing Geo location API, delayed splash screen, mobile application launch icons and talking a little bit about PhoneGap application debugging and architecture. I’m always looking for comments and suggestions, if you have any leave them in the comments under this post or get in touch directly. As always you can get most recent tutorial source code in the compressed format. Have fun!

Read More >
Developing PhoneGap mobile project. Part 2

In the part one of these series we have checked what PhoneGap mobile application framework is, downloaded its latest version and have created our initial first project for iOS smartphone platform. I have also outlined frame for example mobile app we are going to build and the set of web APIs that we will be using to make this example application somewhat useful for its users.

In this part of the tutorial we will take a closer look to PhoneGap framework structure, its main files and will write code to consume data from the web based APIs. Lets call it slightly advanced “Hello World” example which instead of printing just simple text will display 5 yummy receipts retrieved from external web service.
We will continue working on the code of the initial project created in the part one of this tutorial. You can follow the steps we took last time, they are quite simple.
As we have much more code in this part, the all source code for today’s finished tutorial is located at the bottom of the post. Feel free to download and use it for testing. Now, lets get started.

PhoneGap structure for iOS mobile project

Let’s take a look at the structure and contents of the project created by PhoneGap script. Open the project with XCode (key tool for developing iOS based mobile applications). The structure will look the same as I have pictured below, with the key files for iOS project as well as PhoneGap specific www directory and few configuration files.
For iOS apps main.m objective-c implementation file represents the main loop application is constantly running. From the contents of this file we see that AppDelegate is being referenced as a main controller. Quick view to AppDelegate.m implementation file shows us that it sets some configuration parameters for the mobile project. Cache size, window size, splash screen, default start page for view controller (project default is always index.html) and other properties. The main directory where all application files have to be placed is www and they will be served via special custom view (web view).

AppDelegate.m implementation file for newly created PhoneGap iOS project.

PhoneGap project files for iOS

At this time we don’t need to touch anything in the project setup, as we are quite happy with default settings and index.html being the start view for our mobile application. And in PhoneGap world its preferable to change settings via config.xml (it lists plugins and preferences for specific project) as opposed to tweaking objective-c implementation files.

Next we take a closer look at the source of main project file index.html as this is our start view. We see standard HTML5 markup code and the most interesting portion of the code where we are importing JavaScript files.

<script type="text/javascript" src="cordova-2.6.0.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
   app.initialize();
</script>

We need cordova version specific .js file as well as index.js. These 2 are providing all the functionality to the project. JavaScrip file with Cordova version in the name is warping up all PhoneGap framework code written in OS native language and enables JavaScript APIs for our use. index.js file is implementing these APIs. app.initialize(); for example is the call to function created in index.js:

 var app = {

    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },

    // Update DOM on a Received Event
    receivedEvent: function(id) {

        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    }
};

Above is the code from index.js and its quite self explanatory. During the initialize phase we have to bind to events and assign functions to be executed once these events fire. The full list of supported events can be found in PhoneGap documentation. At this time we only are interested in deviceready event and are going to come back to this part of code later to catch events once our mobile application will go to background state, will be retrieved from background state or will loose internet connection.

According to PhoneGap documentation deviceready event is fired once PhoneGap has fully loaded all required code, DOM and JavaScript. After this event we know that app PhoneGap JavaScript APIs are fully available to use.

Adding simple alert message

As a test lets add simple alert message to our iOS application which is displayed once application is started and PhoneGap JavaScript API are ready. For this we need to make sure that config.xml has Notification plugin enabled (by default it does) and add the following code to index.js to receivedEvent section after deviceready has fired.

// Callback function for dismissed alert
function alertDismissed() {
  // do something
}

navigator.notification.alert(
       'DOM and JavaScrip have loaded!!',  // message
       alertDismissed,                     // callback
       'YummyThings Hello World',          // title
       'I know'                            // buttonName
);

If you run your project now it will display alert once application is fully loaded and ready to function.
More about elements for notification.alert you can read in documentation section.

Webservices, Webservices

Now once we have some understanding about the key elements of PhoneGap based mobile application lets add functionality for consuming web API based data and for displaying received information.
Being able to communicate with web based servers and devices is now becoming the key requirement for any useful mobile application. In the part 1 of this tutorial we decided to use Yummly.com API’s for retrieving recipes based on the ingredients our mobile application users like.

Consuming data from 3rd party web services in most cases requires to obtain API credentials and authenticate your API calls by using them. Therefore its a common security practice for mobile app developers not to store such API credentials in the actual mobile application.

In our project we are going to do just that. In the simplified way for this tutorial (but before you go live with your project, make sure your server side code runs securely). I have created the following simple PHP script to represent your server side code.

<?php

// Get what's being sent to us

if ($_GET['q']) $question=$_GET['q'];
if ($_GET['requirePictures']) $rpictures=$_GET['requirePictures'];

////////////////////////////////
// API credentials /////////////

// TODO: please obtain API credentials form developer.yummly.com
$appid = "xxx";
$appkey = "xxx";

// Number of itens in response
$returnitems = 4; //will give us back 4+1=5 items

// Building string for GET request
$requeststr = "http://api.yummly.com/v1/api/recipes?";

$requeststr=$requeststr."_app_id=".$appid;
$requeststr=$requeststr."&_app_key=".$appkey;

$requeststr=$requeststr."&q=".$question;
if ($rpictures) $requeststr=$requeststr."&requirePictures=".$rpictures;

// Debug
//echo $requeststr

// CURL for communicating with web service

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$requeststr);
curl_setopt($ch, CURLOPT_VERBOSE, 1);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

$response = curl_exec($ch);

// We can do some heavy lifting on the server side
// and send back already prepared html from only the elements
// we need.
$response_decoded = json_decode($response, true);

$returnstring = "";

for ($i=0; $i<=$returnitems; $i++) {

  $returnstring = $returnstring."<p><img src='".
  $response_decoded['matches'][$i]['smallImageUrls']['0']."' />Recipe Name: ".
  $response_decoded['matches'][$i]['recipeName'].", it has ".count($response_decoded['matches'][$i]['ingredients'])." ingridients.</p>";
}

echo $returnstring;

?>

If you are not a PHP guru, what this code does – it accepts incoming request from mobile client (with the list of ingredients – no sensitive data being sent over the network), uses received data to make a API call to 3rd party web service, parses received JSON response and returns 5 results wrapped into HTML markup code (not bad for PHP 60 liner, huh?). Feel free to copy this code to your server, or write similar functionality in the programming language you know best. The beauty of web services is that functionality is not dependent on programming language being used.

Making HTTP call from PhoneGap application

Next is our PhoneGap mobile application code. We have to make a HTTP call to our back end server, pass the values of ingredients selected by app user and receive prepared markup with number of responses. We are going to employ one of the most popular JavaScript libraries to do this work for us. I’m talking about jQuery library which is much loved by many web developers and makes great fit for hybrid mobile applications. Download the library and add it to your project by importing in index.html

<script type="text/javascript" src="js/jquery.js"></script>

The following code is added to main index.html file

<script type="text/javascript">
  app.initialize();
</script>

<script type="text/javascript">
$( document ).ready(function() {
  $(".share").click(function (e) {
    $('.content').toggleClass('show');
    e.preventDefault();
  });
});
</script>

<script type="text/javascript" charset="utf-8">

function callWebService(){

  // We don't want API call to be made and data refreshed
  if ($('#yummy').is(':empty')){

    // Adding spinner image until we will get response
    $("#yummy").append("<img class='spinner' src='img/loadinfo.net.gif' />");

    var question = $("#question").val();

    // Log
    console.log("Questions value: " + question);

    //create request url
    var url = "http://your.test.server.url/?q=" + question + "&requirePictures=true";

    // Log
    console.log("Request string: " + url);

    // Call to web server
    $.get(url, function(data) {

    // Clear spinner
    $("#yummy").empty();

    // Add results to HTML
    $("#yummy").html(data);

    // Log received content
    console.log("Received string: " + data);

  }
 );

} // end if

}//end of method

</script>

<div id="menu">
<input id="question" type="text"></input>
<div type="button" onclick="callWebService()" id="webservice_call">Find recipes</div>
<div id="yummy"></div>
</div>

Lets split above code into parts. First I’m using app.initialize() PhoneGap function to initialize all framework JavaScript API’s (even if in this tutorial part we are not really using them). Next I have code which displays drop down menu on the click of the button with id="webservice_call" on the click. This element will not only extend drop down menu, but once clicked will execute another function callWebService(). In it I’m preparing request string to be send to our back end server (by taking input value of text element with id="question"), displaying spinning image until we receive results for our API call and populating drop down list with received values once we get them. I’m using console.log() function in many places to print variable values to the console simply for debugging purposes.

To make our test project UI look beautiful I have reused some of the styles and markup from previous tutorials here on htmlcenter. Once compiled and run this is how our PhoneGap mobile project looks now.

The resulting print screens of loading results and finished recipe list

PhoneGap loading web service data

PhoneGap finished loading web services data

We did a lot of work in this tutorial (well done! for reaching this far) and now have created PhoneGap based mobile application which can consume content from external web servers and display results within iOS view. Similar technique can be used to dynamically change larger portions of mobile application content or styles (load them remotely from your back end if there were any changes made).

Whats next

This is the end of tutorial part 2. In the next part of this tutorial we are adding even more functionality: Local storage and Native Controls. I’m looking forward for any questions, comments and feedback, you can leave them in the comments area under the post or reach out to me on Twitter.

Full source code for what we have done so far can be found and downloaded here. Have fun!

Read More >
Developing PhoneGap mobile project. From start to finish

This is the first part of the tutorial. Second, Third and the last tutorial parts can be found by following the links.

After receiving good reader feedback for HTML5 widgets tutorial for iOS digital books today I’m starting with new tutorial for developing hybrid mobile applications with the help of PhoneGap framework (or Apache Cordova wrapper as some people like to call it).

The goal is to create a fully working and somewhat useful mobile application from the ground up. To make things more interesting and useful for our readers I’m planning to implement (and go into technical specs) today’s most used mobile application functions. Web services (the way for client devices to communicate with servers and each other over the World Wide Web network), Authentication (after which mobile applications can consume online resources on behalf of third parties), Geolocation, Maps and on device Storage.

I’m estimating that it will take little bit of time to get to the end of the project and to write everything in blog post format. Therefore I will split this tutorial into several parts and will publish them separately here on htmlcenter. It will make it easier to follow for everyone who is reading as well.
You are much welcome to join the discussion any time by posting comments or asking questions. There is much work ahead so lets get started!

Why PhoneGap and what is hybrid mobile application?

PhoneGap was created at one of iPhoneDevCamp events by Brock Whitten and Rob Ellis and quickly got attention of good few mobile developers globally. Developers who wanted to use HTML5 and JavaScript code in their mobile projects and wanted mobile apps to still be a native mobile applications. Since then PhoneGap was acquired by Adobe who open sourced it as Apache Foundation project named Apache Cordova.

Mobile applications created with PhoneGap are called hybrid mobile apps as they are not fully native but rather are using native web view type elements within mobile application to display app resources. These applications are different from HTML5 based apps running on the web servers as JavaScript code is created for specific set of custom APIs. PhoneGap framework enables set of custom JavaScript APIs to access mobile device native functionality. The source files for mobile application are HTML markup with CSS for styling and JavaScript for interactivity and accessing native mobile functionality.

Such hybrid mobile apps allow developers to use different programming / scripting languages from OS specific one (like Objective C or Java). In this tutorial I want to show you how to create fully working mobile app for both iOS and Android platforms by using mainly the same HTML5, CSS and JavaScript code base. First we are going to create iOS version and later use the same HTML5 / JavaScript code base for developing Android based application.

Don’t worry if you are quite new to hybrid mobile application development and all of this doesn’t make much sense yet. I’m sure that once you follow this tutorial further things will start to come together.

First step. Downloading PhoneGap framework and starting the project.

At the time of writing this tutorial PhoneGap has over 1200 registered developers in their developer directory. You can also join the developer community and discussion groups but this is not necessary in order to download the recent version of framework. Just go to the download page and get the most recent version of the framework. At the time of writing I have downloaded version 2.6.0.

Contents of downloaded PhoneGap framework

Content of downloaded PhoneGap mobile framework

Once downloaded and unzipped project has several directories in it including documents, change log and actual libraries created for all main mobile operating systems. For our purpose we will need PhoneGap library for iOS devices as the first version of our application will be developed for this mobile OS.

On the official PhoneGap website there is an extensive guide on how to implement PhoneGap library into iOS projects. Based on this guide we need to do the following steps to get started.

Create a new directory for the project. On my development machine I created

~/Documents/Mobile Development/PhoneGap/2.6.0

to keep the track of the PhoneGap version being used. Next we need to run the script from within the downloaded library to create a new XCode project. First navigate to bin directory of unzipped PhoneGap library lib/ios/bin. In the actual script you have to provide package name (unique name which in most cases is reverse url for your company or organization) and project name. Here is the command line I have executed

./create ~/Documents/Development/PhoneGap/2.6.0/YummyThings com.popularowl.phonegap.YummyThings YummyThings

and it has nicely created YummyThings XCode project. Yes, I know, yummy.. But more about this later.

XCode project file was located within newly created YummyThings app directory and after launching it through XCode IDE I have successfully compiled the code. There was one warning however

useSplashScreen is deprecated: Deprecated in Cordova 2.5.
Add/Remove the SplashScreen plugin instead of setting this property

It has to do with the use of viewController.useSplashScreen iOS View Controller properties and it seams that PhoneGap wants us to use their specific plugin (hm.. I just used out of the box code). Not a big deal and we can fix this warning later.

Initial iOS project setup after creating it with default script

Initial file structure after iOS project setup with cordova

In the mean time I have launched application in iPhone simulator and it started nicely. This means we are up and running.

Out of the box PhoneGap iOS application running in iPhone simulator

sample PhoneGap application running on iOS simulator

How to find yummy things? And what can we do about it

Now then we have our initial iOS app project setup and running with PhoneGap it’s time to talk a little about the application we are going to develop. There is a nice site online called ProgrammableWeb. Its packed with API’s and has big list of them summarized and available to use for developer projects. After some searching I found API provided by Yummly.com folks. On Yummly web site visitors can find recipes for many yummy meals based on ingredients they like. Their API makes it easy to do this search in programmatic way. Sounds like a great fit for our YummyThings mobile application. It will give users an option to choose the ingredients they like, and get a bunch of nice recipes of yummy dishes. We will even store ingredients and recipes on the actual device so app users can view them later or share with their friends. You will need to obtain an API key from Yummly folks in order to work with their API, and there is a free plan with up to 500 API calls per day. More than enough for our sample application.

Summary and what’s next

This is the end of part one. We have looked at what PhoneGap and hybrid mobile applications are, successfully created our initial PhoneGap project for iOS and tested it with XCode and iPhone simulator.  Next time we are going to look through the key files in the project, implement functionality for web service communication and consuming data from Yummly APIs. I hope you are looking forward.

If you have any questions or feedback leave them in comments section under the post.

Read More >
Creating HTML5 widgets for Apple iBook applications

Recently I had a chance to take a closer look at relatively new tool for creating interactive iPad tablet reading experiences called iBooks Author. It was released by Apple in January 2012 and is aimed at book authors and publishers to allow for an easy publishing of their books on Apple iBook platform. Application supports its own format .ibooks as well as .pdf and .ePub formats for exporting.

But what really caught my attention was the possibility to embed interactive elements inside actual ebooks. It can be done in the form of HTML5 widgets, with CSS styling and JavaScript support for building interactivity.  As it was a good fit for one of interactive digital mobile content projects we will be crafting at PopularOwl and I went through the process of creating and adding HTML5 widget to iBook project to understand how it all comes together.

In this tutorial I’m going to walk you through the steps for building fully working HTML5 widget to be used in iBooks Author projects. This sample widget will help eBook authors to easily add social follow option to their digital books so their readers can interact from within the eBook.

Source code for finished widget project is located at the bottom of this tutorial, feel free to download and test it. The final result:

html5 widget in ibook author

What is HTML5 widget?

HTML5 widgets have .wdgt file format and are packaged sets of markup, style, JavaScript and configuration files. Apple recognizes .wdgt type directories as widgets on their OSX operating system and, as we will learn, on some mobile development tools as well. Simply speaking these widgets are just standard directories with additional extensions in their name. Such widget directory must contain certain files in it to work as functioning widget but more about it latter in this tutorial.

Tools for creating HTML5 widgets

As widgets are just simple directories containing HTML, CSS, JavaScript and .plist files there are no requirements to use specific tool to create or edit them. Any text editor will do as long as it can open and edit these file types. I personally use Coda 2 but I’m sure you have your preferences.
For automated HTML5 widget creation Apple have a tool called Dashcode.
But for purposes of this tutorial we are going to create all files manually as we want to understand how widgets are build.

Lets get going!

There are 3 required files you have to supply in order to create working HTML5 widget. Main HTML file with .html extension (no naming limitations on this one), Default.png – the image file which will be displayed to users on the eBook page (this has to be named exactly like this and is case sensitive) and Info.plist file for storing widget settings – also has to be named exactly that.

For this tutorial I’m going to use example code of HTML5 dropdown menu which is styled with simple CSS styles and has a little bit of jQuery for interactive part. It looks like this:

example menu for html5 widget

HTML5 widgets for iBooks have great support for JavaScript scripting language, its libraries and CSS styles (though I was not able to find exact specifications on any Apple developer sites). In my index.html I have the following markup:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="chrome=1,IE=9" />
    <meta name="viewport" content="user-scalable=yes, width=600" />
    <script src="jquery.js" type="text/javascript"></script>
    <title>DropDown</title>

    <style>

        body {
            background: #55bed5;
            font-family: 'Helvetica Neue';
            font-weight: lighter;
        }

        ul {
            margin: 0;
            padding: 0;
        }

        li {
            list-style-type: none;
            margin:0;
            padding: 10px 0;
        }

        a {text-decoration: none; color:#333;}
        p {margin: 0;padding: 0; clear:none;text-shadow: 1px 1px #fff;}

        #menu {
            width: 260px;
            background: #efefef;
            margin: 30px 0px 0px 70px;
            border-radius: 5px;
            box-shadow: 0 10px 0 -3px rgba(0,0,0,.2),0 2px 0 rgba(0,0,0,.1);
            -webkit-transform: scale(.8);
            -moz-transform: scale(.8);
            -ms-transform: scale(.8);
            -o-transform: scale(.8);
            transform: scale(.8);
            -webkit-transition: all .3s ease;
            -moz-transition: all .3s ease;
            -ms-transition: all .3s ease;
            -o-transition: all .3s ease;
            transition: all .3s ease;

        }        

        #menu:hover {
            -webkit-transform: scale(1);
            -moz-transform: scale(1);
            -ms-transform: scale(1);
            -o-transform: scale(1);
            transform: scale(1);
            -webkit-transition: all .3s ease;
            -moz-transition: all .3s ease;
            -ms-transition: all .3s ease;
            -o-transition: all .3s ease;
            transition: all .3s ease;
        }

        .share {
            text-align: center;
            padding: 5px;
            background: #ed6b3a;
            border-radius: 5px 5px 0 0;
            border-bottom: 5px solid rgb(218, 109, 63);    
        }

        .share:hover {

            border-bottom: 5px solid rgb(165, 80, 45);
            box-shadow:inset 0 -1px 0 rgba(255, 255, 255, .2),
            inset 0 1px 0 rgba(255, 255, 255, .2);

        }

        .content {height: 0;overflow: hidden ;opacity:0;}
        .show {
            height: 253px;
            opacity:1;
        }

        li {
            box-shadow: 0 1px 0 rgba(0,0,0,.1);
            position: relative;
            padding: 15px;
            text-align: center;
        }

        li img {
            padding-right: 10px;
            margin-right: 10px;
            float: left;
            border-right: 1px solid #eaeaea;
        }

        li:hover {background: rgba(20, 20, 20, 0.1)}

        li:hover,.share:hover,.content {
            -webkit-transform: translate3d(0, 0, 0);
            -moz-transform: translate3d(0, 0, 0);
            -ms-transform: translate3d(0, 0, 0);
            -o-transform: translate3d(0, 0, 0);
            transform: translate3d(0, 0, 0);
            -webkit-transition: all .6s ease;
            -moz-transition: all .6s ease;
            -ms-transition: all .6s ease;
            -o-transition: all .6s ease;
            transition: all .6s ease;

        }

        .show {
            -webkit-transition: all .6s ease;
            -moz-transition: all .6s ease;
            -ms-transition: all .6s ease;
            -o-transition: all .6s ease;
            transition: all .6s ease;
        }

    </style>

</head>
<body>

<script type="text/javascript">
    $( document ).ready(function() {
    $(".share").click(function (e) {
      $('.content').toggleClass('show');
      e.preventDefault();
    });
    });
</script>

<div id="menu">
    <a href="#"><div><img src="img/N3osT4l.png" alt=""></div></a>
    <div>
        <ul>
            <a href="#"><li><img src="img/sEKPZan.png"><p>Facebook</p></li></a>
            <a href="#"><li><img src="img/wefpyCe.png"><p>Twitter</p></li></a>
            <a href="#"><li><img src="img/TIhzUN3.png"><p>Google+</p></li></a>
            <a href="#"><li><img src="img/UpTP5kJ.png"><p>Pinterest</p></li></a>
            <a href="#"><li><img src="img/IGNnYUg.png"><p>Dribbble</p></li></a>
        </ul>
    </div>
</div>

</body>
</html>

As you can see this is pretty simple example which requires jQuery library and several images to be present. For our purpose I have downloaded the latest version of jQuery library and packed images in to separate img directory within projects main dir. Now we have to create Info.plist file which is used for storing settings and has its own XML format. If you are new to Apple developer world I recommend you to Google and read more about this specific XML format as you are going to find it in every development project if its to do with iOS / MacOSX. Its not overall complicated. In the mean time here is the content of my Info.plist file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>AllowNetworkAccess</key>
    <true/>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleDisplayName</key>
    <string>DropMenu</string>
    <key>CFBundleIdentifier</key>
    <string>com.popularowl.widget.ibook</string>
    <key>CFBundleName</key>
    <string>DropMenu</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>CFBundleVersion</key>
    <string>1.0</string>
    <key>Height</key>
    <string>400</string>
    <key>MainHTML</key>
    <string>index.html</string>
    <key>Width</key>
    <string>400</string>
</dict>
</plist>

Its quite self explanatory as each setting has a name and the corresponding value. In order to create Default.png image I took a print screen of HTML5 menu example displayed by the web browser. One note here: if you haven’t declared the widget size in your Info.plist file (we did) the dimensions of Default.png image will be used as the size for your widget. Make sure you are specifying the right height and width for your project.
Once all files are created we need to add extension .wdgt to project directory. This is done by simply renaming directory (MacOSX will ask you to confirm and you just say yes).
Whats left now is to open iBooks Author application, start the new eBook project and choose to insert widget from the top menu. Once you get dialog window there will be some pre made widgets as well as HTML option at the bottom of the list. Once selected it will give you a container within iBook where you can drag & drop your newly created widget. You should now see a preview of functioning dropdown menu. Connect your test iPad device, hit preview and welcome to interactive eBooks world.

Conclusions

HTML5 widgets are simple way to make digital eBooks more interactive. In my opinion the strong side is that you can reuse HTML5 and JavaScript content from other mobile or web projects you worked on with simply adopting already existing code to the screen size etc. And of course remember that eBook is not a smartphone game, so be cautious with overloading it with to much interactivity.

Source code for sample widget can be found here.

Read More >

Join our team

Do you enjoy technical writing? Care about cross platform mobile apps, HTML5, Javascript and Ninja's? Write for us! We would like to hear from you, get in touch!

Worth your attention