Cordova (aka PhoneGap) 3.x Tutorial

July 2nd 2014: An updated version of this tutorial is available here


In this tutorial, you’ll create a fully functional employee directory application with Cordova.

What you will learn:

  • How to use different local data storage strategies.
  • How to use several Cordova APIs such as Geolocation, Contacts, and Camera.
  • How to handle specific mobile problems such as touch events, scrolling, styling, page transitions, etc.
  • How to build an application using a single-page architecture and HTML templates.
  • How to build (compile and package) an application locally using the Cordova CLI (Command Line Interface).


To complete this workshop, all you need is a code editor, a modern browser, and a connection to the Internet.

A working knowledge of HTML and JavaScript is assumed, but you don’t need to be a JavaScript guru.

A mobile device or a Mobile SDK is not a requirement for this tutorial. However, if you want to run and test the application on a mobile device or on an emulator for a mobile platform supported by Cordova, you need the Mobile SDK for that platform (iOS SDK, Android SDK, etc.) installed on your system. If you don’t want to install a Mobile SDK, you’ll be able to test your application in a browser on your computer.

Part 1: Creating a Cordova Project

  1. Make sure an up-to-date version of Node.js is installed on your system.
  2. Open Terminal (Mac) or a Command window (Windows), and type the following command to install the Cordova CLI:
    npm install -g cordova

    or on a Mac:

    sudo npm install -g cordova
  3. Navigate to a directory where you store projects on your system. For example:
    cd ~/Projects
  4. Create a project called “workshop”:
    cordova create workshop com.yourname.workshop Workshop
  5. Navigate to the project directory:
    cd workshop
  6. Add the platforms you want to support. For example, to add support for iOS and Android, type:
  7. cordova platforms add ios
    cordova platforms add android
  8. Make sure you are in the “workshop” directory, and add basic plugins to your projects:
    cordova plugin add org.apache.cordova.device
    cordova plugin add org.apache.cordova.console
  9. Examine the directory structure under workshop.

Part 2: Building a Cordova Project


You need the iOS SDK installed on your computer to build an iOS version of your application using the steps below.

cordova build ios

The project is built in the workshop/platforms/ios folder. Double-click Workshop.xcodeproj to open the project in XCode, and run it in the emulator or on your device.

You can also run the application in the iOS emulator directly from the command line. First install ios-sim:

sudo npm install -g ios-sim

Then run the application in the iOS emulator:

cordova emulate ios


You need the Android SDK installed on your computer to build an Android version of your application using the steps below.

To build the project in the workshop/platforms/android folder and run it on an Android device connected to your computer using a USB cable, type:

cordova run android

To build the project in the workshop/platforms/android folder and run it in the Android emulator, type:

cordova emulate android


Part 3: Setting Up the Workshop Files

  1. Download the assets for the workshop here or clone this repository
  2. .

  3. Unzip the file anywhere on your file system.
  4. Delete the contents of your project’s workshop/www folder with the exception of the config.xml file.
  5. Copy the contents of cordova-tutorial-master/www into your project’s workshop/www folder.
  6. Build and test your application: If you have a Mobile SDK installed on your system, repeat the steps in Part 2 above. If you don’t, simply open index.html in a browser on your computer.
  7. Type a few characters in the search box to search employees by name. Clicking an employee link doesn’t produce any result at this time.
Step-by-step solutions are available in the cordova-tutorial-master/solutions folder

Part 4: Choosing a Local Storage Option

Step 1: Explore different persistence mechanisms

Open the following files in workshop/js/adapters, and explore the different persistence adapters:

  1. MemoryAdapter (in memory-adapter.js)
  2. JSONPAdapter (in jsonp-adapter.js)
  3. LocalStorageAdapter (in localstorage-adapter.js)
  4. WebSqlAdapter (in websql-adapter.js)

Step 2: Test the application with different persistence mechanisms

The application is initially configured to work with the in-memory datastore. To change the local persistence mechanism for the application:

  1. In index.html: instead of memory-adapter.js, import the .js file for the data adapter of your choice: jsonp-adapter.js, localstorage-adapter.js, or websql-adapter.js.
  2. In js/app.js, replace the instantiation of MemoryAdapter with the instantiation of the data adapter you imported in the previous step: JSONPAdapter, LocalStorageAdapter, or WebSqlAdapter.
  3. Test the application.

Part 5: Using Native Notification

A default JavaScript alert gives away the fact that your application is not native. In this section, we set up the basic infrastructure to display native alerts when the application is running on a device, and fall back to default JavaScript alerts when it is running in the browser.

  1. Add the native dialogs plugin to your project:
    cordova plugin add org.apache.cordova.dialogs
  2. In index.html, add the following script tag (as the first script tag at the bottom of the body):
    <script src="cordova.js"></script>

    This instructs the Cordova CLI to inject a platform specific version of cordova.js at build time. In other words, cordova.js doesn’t need to be (and shouldn’t be) present in your project/www folder.
  3. When running on a device with the navigator.notification object available (the dialogs plugin is installed), override the window.alert() function and replace its default implementation with a call to navigator.notification.alert(). Add this code to the “Event Registration” block:
    document.addEventListener('deviceready', function () {
        if (navigator.notification) { // Override default HTML alert with native dialog
            window.alert = function (message) {
                    message,    // message
                    null,       // callback
                    "Workshop", // title
                    'OK'        // buttonName
    }, false);
  4. Test the application: click the Help button.

    When you run the application in the browser, you should see a standard browser alert.
    When you run the application on your device, you should see a native alert.

Part 6: Avoid the 300ms Click Delay

  1. Test the application on your iOS device or in the iOS emulator: Tap the Help button, and notice the delay before the dialog appears.
  2. This delay occurs because the operating system is waiting roughly 300ms to see if the user is going to tap the target again (and therefore perform a double-tap).
  3. In index.html, add the following script tag:
    <script src="lib/fastclick.js"></script>

    FastClick is an open source library built by the Financial Times. More information here.

  4. In app.js, register FastClick inside the deviceready event handler.

  5. Test the application: Click the Help button. The message should now appear without delay.

Part 7: Setting Up a Single-Page Application

A “Single-Page Application” is a web application that lives within a single HTML page. The “views” of the application are injected into and removed from the DOM as needed as the user navigates through the app. A single-page application architecture is particularly well suited for mobile apps:

  • The absence of page refreshes provides a more fluid and closer to native experience.
  • The UI is entirely created at the client-side with no dependency on a server to create the UI, making it an ideal architecture for applications that work offline.

In this section, we set up the basic infrastructure to turn Employee Directory into a single-page application.

  1. In index.html: remove the HTML markup inside the body tag (with the exception of the script tags).
  2. Inside the immediate function in app.js, define a function named renderHomeView() (right after the findByName function). Implement the function to programmatically add the Home View markup to the body element.
    function renderHomeView() {
        var html =
            "<h1>Directory</h1>" +
            "<input class='search-key' type='search' placeholder='Enter name'/>" +
            "<ul class='employee-list'></ul>";
        $('.search-key').on('keyup', findByName);
  3. Modify the data adapter initialization logic: when the adapter has been successfully initialized, call the renderHomeView() function to programmatically display the Home View.
    var adapter = new MemoryAdapter();
    adapter.initialize().done(function () {
  4. Since you moved the registration of the keyup event inside the renderHomeView() function, make sure you remove the original event registration in the Event Registration section.
  5. Since the Help button is no longer there, remove the click event handler for the help button (in the Event Registration section).
  6. Test the application.

Part 8: Using Handlebars Templates

Writing HTML fragments in JavaScript and programmatically inserting them into the DOM is tedious. It makes your application harder to write and harder to maintain. HTML templates address this issue by decoupling the UI definition (HTML markup) from your code. There are a number of great HTML template solutions, including Mustache.js, Handlebars.js, and Underscore.js to name a few.

In this section, we create two templates to streamline the code of the Employee Directory application. We use Handlebars.js but the same result can be achieved using the other HTML template solutions.

Modify index.html as follows:

  1. Add a script tag to include the handlebars.js library:
    <script src="lib/handlebars.js"></script>
  2. Create an HTML template to render the Home View. Add this script tag as the first child of the body tag:
    <script id="home-tpl" type="text/x-handlebars-template">
        <div class="topcoat-navigation-bar">
            <div class="topcoat-navigation-bar__item center full">
                <h1 class="topcoat-navigation-bar__title">Employee Directory</h1>
        <div class="search-bar">
            <input type="search" placeholder="search" class="topcoat-search-input search-key">
        <div class="topcoat-list__container">
            <ul class="topcoat-list list employee-list"></ul>
  3. Create an HTML template to render the employee list items. Add this script tag immediately after the previous one:
    <script id="employee-li-tpl" type="text/x-handlebars-template">
        <li class="topcoat-list__item">
            <a href="#employees/{{id}}">
                <img src="assets/pics/{{pic}}">
                <p>{{firstName}} {{lastName}}</p>
                <span class="chevron"></span><span class="count">{{reports}}</span>
  4. Add topcoat-mobile-light.css and styles.css to the head of index.html
    <link href="assets/topcoat/css/topcoat-mobile-light.css" rel="stylesheet">
    <link href="assets/css/styles.css" rel="stylesheet">

Modify the immediate function in app.js as follows:

  1. Immediately before the adapter variable declaration, declare two variables that hold the compiled version of the templates defined above:
    var homeTpl = Handlebars.compile($("#home-tpl").html());
    var employeeLiTpl = Handlebars.compile($("#employee-li-tpl").html());
  2. Modify renderHomeView() to use the homeTpl template instead of the inline HTML:
    function renderHomeView() {
        $('.search-key').on('keyup', findByName);
  3. Modify findByName() to use the employeeLiTpl template instead of the inline HTML:
    function findByName() {
        adapter.findByName($('.search-key').val()).done(function (employees) {
  4. Test the application.

Part 9: Creating a View Class

It’s time to provide the application with some structure. If we keep adding all the core functions of the application to the immediate function that bootstraps the app, it will very quickly grow out of control. In this section we create a HomeView object that encapsulates the logic to create and render the Home view.

Step 1: Create the HomeView Class

  1. Create a file named HomeView.js in the js directory, and define a HomeView constructor implemented as follows:
    var HomeView = function (adapter, template, listItemTemplate) {
  2. The constructor function takes three arguments: the data adapter, the Home View template, and the employee list item template.
  3. Define an initialize() function inside the HomeView constructor. Define a div wrapper for the view. The div wrapper is used to attach the view-related events. Invoke the initialize() function inside the HomeView constructor function.
    var HomeView = function (adapter, template, listItemTemplate) {
        this.initialize = function () {
            // Define a div wrapper for the view. The div wrapper is used to attach events.
            this.el = $('<div/>');
            this.el.on('keyup', '.search-key', this.findByName);
  4. Move the renderHomeView() function from app.js to the HomeView class. To keep the view reusable, attach the HTML to the div wrapper (this.el) instead of the document body. Because the function is now encapsulated in HomeView, you can also rename it from renderHomeView() to just render().
    this.render = function() {
        return this;
  5. Move the findByName() function from app.js to HomeView.
    this.findByName = function() {
        adapter.findByName($('.search-key').val()).done(function(employees) {

Step 2: Using the Home View

  1. In index.html, add a script tag to include HomeView.js (just before the script tag for app.js):
    <script src="js/HomeView.js"></script>
  2. In app.js, remove the renderHomeView() function from the immediate function.
  3. Remove the findByName() function from the immediate function.
  4. Modify the adapter initialization logic to display the Home View when the adapter has been successfully initialized. Pass the adapter, the Home View template, and the employee list item template as arguments to the Home View constructor.
    adapter.initialize().done(function () {
        $('body').html(new HomeView(adapter, homeTpl, employeeLiTpl).render().el);
  5. Test the application

Part 10: Implementing Native Scrolling

Test the application. Specifically, test the list behavior when the list is bigger than the browser window (or the screen). Notice that the entire view (including the header) is scrolling. To anchor the header at the top of the screen, and scroll the employee list only:

  1. In the Home Page template, add a css class named scroller to the div surrounding the employee list ul.
    <div class="topcoat-list__container scroller">
        <ul class="topcoat-list list employee-list"></ul>
  2. In assets/css/styles.css define the scroller class as follows:
    .scroller {
        overflow: auto;
        -webkit-overflow-scrolling: touch;
        position: absolute;
        top: 141px;
        bottom: 0px;
        left: 0px;
        right: 0px;
  3. Test the application.

On iOS, you can still scroll down the web view (including the header). To disable this behavior, open config.xml in the workshop/www folder and add the following preference as the last line within the widget tag:

<preference name="DisallowOverscroll" value="true" />

If the platforms you target support touch-based scrolling of fixed regions, this approach is all you need. If not, you’ll need to implement a programmatic approach, typically with the help of a library such as iScroll.

Part 11: View Routing

In this section, we add an employee details view. Since the application now has more than one view, we also add a simple view routing mechanism that uses the hash tag to determine whether to display the home view or the details view for a specific employee.

Step 1: Create the employee template

Open index.html and add a template to render a detailed employee view:

<script id="employee-tpl" type="text/x-handlebars-template">
    <div class="topcoat-navigation-bar">
        <div class="topcoat-navigation-bar__item left quarter">
            <a class="topcoat-icon-button--quiet back-button" href="#">
                <span class="topcoat-icon topcoat-icon--back"></span>
        <div class="topcoat-navigation-bar__item center half">
            <h1 class="topcoat-navigation-bar__title">Employee</h1>
    <div class='details'>
        <img src="assets/pics/{{pic}}" class="employee-image">
        <h1>{{firstName}} {{lastName}}</h1>
        <div class="topcoat-list__container scroller">
            <ul class="topcoat-list list actions">
                {{#if managerId}}
                <li class="topcoat-list__item"><a href="#employees/{{managerId}}"><p>View Manager</p><p>{{managerName}}</p><div class="action-icon icon-manager"/></a></li>
                <li class="topcoat-list__item"><a href="tel:{{officePhone}}"><p>Call Office</p><p>{{officePhone}}</p><div class="action-icon icon-call"/></a></li>
                <li class="topcoat-list__item"><a href="tel:{{cellPhone}}"><p>Call Cell</p><p>{{cellPhone}}</p><div class="action-icon icon-call"/></a></li>
                <li class="topcoat-list__item"><a href="sms:{{cellPhone}}"><p>SMS</p><p>{{cellPhone}}</p><div class="action-icon icon-sms"/></a></li>
                <li class="topcoat-list__item"><a href="mailto:{{email}}"><p>Email</p><p>{{email}}</p><div class="action-icon icon-mail"/></a></li>

Step 2: Create the EmployeeView class

  1. Create a file named EmployeeView.js in the js directory, and define an EmployeeView constructor implemented as follows:
    var EmployeeView = function(adapter, template, employee) {
  2. Define an initialize() function inside the HomeView constructor. Define a div wrapper for the view. The div wrapper is used to attach the view related events. Invoke the initialize() function inside the EmployeeView constructor function.
    var EmployeeView = function(adapter, template, employee) {
        this.initialize = function() {
            this.el = $('<div/>');
  3. Define a render() function implemented as follows:
    this.render = function() {
        return this;
  4. In index.html, add a script tag to include EmployeeView.js (just before the script tag for app.js):
    <script src="js/EmployeeView.js"></script>

Step 3: Implement View Routing

  1. Open app.js. In the Local Variables section, declare a variable named employeeTpl that holds the compiled template for the employee details view:
    var employeeTpl = Handlebars.compile($("#employee-tpl").html());
  2. In the Local Variables section, declare a variable named detailsURL that holds a regular expression to match employee details URLs.
    var detailsURL = /^#employees\/(\d{1,})/;
  3. In the Event Registration section, add an event listener to listen to URL hash tag changes:
    $(window).on('hashchange', route);
  4. In the Local Functions section, define a route() function to route requests to the appropriate view:
    • If there is no hash tag in the URL, display the HomeView
    • If there is a hash tag matching the pattern for an employee details URL, display an EmployeeView for the specified employee.
    function route() {
        var hash = window.location.hash;
        if (!hash) {
            $('body').html(new HomeView(adapter, homeTpl, employeeLiTpl).render().el);
        var match = hash.match(detailsURL);
        if (match) {
            adapter.findById(Number(match[1])).done(function(employee) {
                $('body').html(new EmployeeView(adapter, employeeTpl, employee).render().el);
  5. Modify the adapter initialization logic to call the route() function when the adapter has been successfully initialized:
    adapter.initialize().done(function () {
  6. Test the application.

Part 12: Using the Location API

In this section, we add the ability to tag an employee with his/her location information. In this sample application, we display the raw information (longitude/latitude) in an alert. In a real-life application, we would typically save the location in the database as part of the employee information and show it on a map.

The code below works when running the application as a Cordova app on your device. It should also work in Chrome on the desktop when the page is served with the http:// protocol, and in Firefox, regardless of the protocol (http:// or file://).
  1. Add the geolocaton plugin to your project
    cordova plugin add org.apache.cordova.geolocation
  2. In index.html, add the following list item to the employee-tpl template:
    <li class="topcoat-list__item"><a href="#" class="add-location-btn"><p>Add Location</p></a></li>
  3. In the initialize() function of EmployeeView, register an event listener for the click event of the Add Location list item.
    this.el.on('click', '.add-location-btn', this.addLocation);

    Make sure you add this line as the last line of the initialize() function (after this.el is assigned).

  4. In EmployeeView, define the addLocation event handler as follows:
    this.addLocation = function(event) {
            function(position) {
                alert(position.coords.latitude + ',' + position.coords.longitude);
            function() {
                alert('Error getting location');
        return false;
  5. Test the Application

Part 13: Using the Contacts API

In this section, we use the Cordova Contacts API to provide the user with the ability to add an employee to the device’s contact list.

The code below only works when running the application on your device as a Cordova app. In other words, you can’t test it in a browser on your computer.
  1. Add the contacts plugin to your project
    cordova plugin add org.apache.cordova.contacts
  2. In index.html, add the following list item to the employee template:
    <li class="topcoat-list__item"><a href="#" class="add-contact-btn"><p>Add to Contacts</p></a></li>
  3. In the initialize() function of EmployeeView, register an event listener for the click event of the Add to Contacts list item:
    this.el.on('click', '.add-contact-btn', this.addToContacts);
  4. In EmployeeView, define the addToContacts event handler as follows:
    this.addToContacts = function(event) {
        if (!navigator.contacts) {
            alert("Contacts API not supported", "Error");
        var contact = navigator.contacts.create(); = {givenName: employee.firstName, familyName: employee.lastName};
        var phoneNumbers = [];
        phoneNumbers[0] = new ContactField('work', employee.officePhone, false);
        phoneNumbers[1] = new ContactField('mobile', employee.cellPhone, true);
        contact.phoneNumbers = phoneNumbers;;
        return false;
  5. Test the Application

Part 14: Using the Camera API

In this section, we use the Cordova Camera API to provide the user with the ability to take a picture of an employee, and use that picture as the employee’s picture in the application. We do not persist that picture in this sample application.

The code below only works when running the application on your device as a Cordova app. In other words, you can’t test it in a browser on the desktop.
  1. Add the camera plugin to your project
    cordova plugin add
  2. In index.html, add the following list item to the employee template:
    <li class="topcoat-list__item"><a href="#" class="change-pic-btn"><p>Change Picture</p></a></li>
  3. In the initialize() function of EmployeeView, register an event listener for the click event of the Change Picture list item:
    this.el.on('click', '.change-pic-btn', this.changePicture);
  4. In EmployeeView, define the changePicture event handler as follows:
    this.changePicture = function(event) {
        if (! {
            alert("Camera API not supported", "Error");
        var options =   {   quality: 50,
                            destinationType: Camera.DestinationType.DATA_URL,
                            sourceType: 1,      // 0:Photo Library, 1=Camera, 2=Saved Album
                            encodingType: 0     // 0=JPG 1=PNG
            function(imageData) {
                $('.employee-image', this.el).attr('src', "data:image/jpeg;base64," + imageData);
            function() {
                alert('Error taking picture', 'Error');
        return false;
  5. Test the Application

Part 15: Sliding Pages with CSS Transitions

Modify index.html as follows:

  1. Add pageslider.css inside the head tag in index.html:
    <link href="assets/css/pageslider.css" rel="stylesheet">
  2. Add a script tag to include the pageslider.js library:
    <script src="lib/pageslider.js"></script>
PageSlider is a micro library I host on GitHub here.

Modify app.js as follows:

  1. In the Local Variables section, declare an instance of the PageSlider object as follows:
    var slider = new PageSlider($('body'));
  2. In the route() function, replace the calls to $(‘body’).html() with calls to slider.slidePage() passing the same argument to the function.
    slider.slidePage(new HomeView(adapter, homeTpl, employeeLiTpl).render().el);


    slider.slidePage(new EmployeeView(adapter, employeeTpl, employee).render().el);

Part 16: Explore Other Implementations

  • Pingback: New Cordova/PhoneGap 3.x Tutorial | Christophe Coenraets()

  • Thanks Christophe,

    I search these type tutorial from long time.

    • anupam

      yes agree… but it will more better if one zip example or video also available ..

      It is very help full for beginners thanks a lot sir

  • Tiendq

    Thanks, it’s the best Cordova basic tutorial until now, I believe so :)

    I also have a couple of questions:

    1. FastClick only solves delay issue, there’s nothing here mentioned about touch events, we need them to implement active state of list items and buttons. Can you add a section for it?

    2. How can use PageSlider to make difference sliding effects e.g. slide in, out, up, down, forward/back?


  • Great efforts! Thanks for such a detailed tutorial Christophe!

    I have a question here concerning Cordova(PhoneGap) command line tool. It seems “cordova” and “phonegap” are not yet convergent for the moment. For example, there is no “phonegap platforms add ios”, adding a plugin requires “phonegap local plugin add …”.

    So when should we use cordova and when should we use phonegap? For the time being, are they maintained in the same level?

    Thank you!

  • Christophe Coenraets

    1. You can manage the state of list items in CSS. Look at styles.css for an example:
    .list li:active {
    background-color: #d6d6d6;
    2. PageSlider is really a very simple micro library provided as a sample. It does support left and right directions, but not up and down. It can easily be extended though.

    • anupam

      It is very help full for beginners thanks a lot sir

      can you send me a zip folder for more help

  • Christophe Coenraets

    @Qian: The PhoneGap CLI is built on top of the Cordova CLI. The PhoneGap CLI is meant to be a bit higher level (for example, platforms are added implicitly). It is also meant to support additional services that are not part of Cordova. At his time, the only example of that is PhoneGap Build, which is why the PhoneGap CLI has those “local” and “remote” options that the Cordova CLI doesn’t have:
    phonegap local build ios (builds locally: you need the iOS SDK)
    phonegap remote build ios (builds in the cloud using PhoneGap build: you don’t need the iOS SDK installed locally)

    • Hi Christophe. I see that you put in the title “Cordova (aka PhoneGap)”. Could you clarify me if some change is expected with this framework? Thanks. Regards.

  • Thank you very much, I am very thankful about this.

  • Hernan

    Excellent Tutorial, Thanks!. I had an issue when deploy it to my device for testing purpose (Android Sony Xperia S), in “HomeView” the list does not scroll up and down, but in “EmployeeView” it does.

    • Andrea

      I’m having the same problem.

      How did you solve it Hernan?

      • michas

        Easy solution is to change height of chevron icon in:
        styles.css line 173 to 42px.

    • Michael Oryl

      I believe I know the answer to that. I saw it, too. It was a CSS problem. There were actually two scrolling areas, which you could plainly see if you looked at the web app in a web browser. That’s how I figured it out.

      In topcoat-light-mobile.css at line 1508 you see this:

      .topcoat-list {
      padding: 0;
      margin: 0;
      font: inherit;
      color: inherit;
      background: transparent;
      border: none;
      cursor: default;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
      overflow: auto; /* Change to ‘visible’ to get around the issue */
      -webkit-overflow-scrolling: touch;

      If you change that overflow: auto to overflow: visible, the problem will be fixed.

      I don’t know what other issues that might cause, though, so it would likely be best to override it in the template in index.html:

      Hope that helps.

      • Michael Oryl

        It would look like this:

        <ul class=”topcoat-list list employee-list” style=”overflow: visible”></ul>

        • Ben

          Thank you for sharing your solution Michael :-)

          Your comment led me to fix the problem by removing the scroller class from the div (the suggested location in the tutorial) and relocate it on the ul tag, i.e: –

          Maybe Christophe made a mistake in the tutorial and meant to add the scroller class to the ul?

          • Hamid

            It works for me

  • Hey I noticed you accidentally created a global variable in localstorage-adapter.js on line 31 –

    var deferred = $.Deferred(),
    employees = JSON.parse(window.localStorage.getItem(“employees”)),
    employee = null; // <– ruh roh no comma
    l = employees.length; // <– global

    Thank you for the tutorial.

    • Christophe Coenraets

      Good Catch! Thanks Ross. Fixed and pushed to GitHub.

  • Geovane

    What a great tutorial!

    It suits very well for me, I have fired my neurons trying to find a great way to do the page routing, thank you very very much!

  • can’t add android, here’s the script:

    c:\Cordova\workshop>cordova platforms add android
    Installing cordova library for android…
    Downloading cordova library for android…
    Download complete
    Installing cordova library for android…
    Creating android project…


    throw e;
    Error: An error occured during creation of android sub-project.

    throw e;
    Error: ERROR : executing command ‘ant’, make sure you have ant installed and add
    ed to your path.
    at C:\Users\Andrei\.cordova\lib\android\cordova\3.3.0\bin\lib\check_reqs.js:
    at ChildProcess.exithandler (child_process.js:641:7)
    at ChildProcess.EventEmitter.emit (events.js:98:17)
    at maybeClose (child_process.js:735:16)
    at Socket. (child_process.js:948:11)
    at Socket.EventEmitter.emit (events.js:95:17)
    at Pipe.close (net.js:466:12)

    at C:\Users\Andrei\AppData\Roaming\npm\node_modules\cordova\src\platform.js:
    at ChildProcess.exithandler (child_process.js:641:7)
    at ChildProcess.EventEmitter.emit (events.js:98:17)
    at maybeClose (child_process.js:735:16)
    at Socket. (child_process.js:948:11)
    at Socket.EventEmitter.emit (events.js:95:17)
    at Pipe.close (net.js:466:12)

    any ideas?

    • additionally, for ios i get:

      c:\Cordova\workshop>cordova platforms add ios
      Creating ios project…


      throw e;
      Error: An error occured during creation of ios sub-project.
      ‘”C:\Users\Andrei\.cordova\lib\ios\cordova\3.3.0\bin\create”‘ is not recognized
      as an internal or external command,
      operable program or batch file.

      at C:\Users\Andrei\AppData\Roaming\npm\node_modules\cordova\src\platform.js:
      at ChildProcess.exithandler (child_process.js:641:7)
      at ChildProcess.EventEmitter.emit (events.js:98:17)
      at maybeClose (child_process.js:735:16)
      at Process.ChildProcess._handle.onexit (child_process.js:802:5)

      thank you in advance Christophe! I am really looking forward to progressing past part 1 :)

      • I installed ANT, that didn’t resolve the issue. This is on Windows 8.1, if that makes any difference.

    • Ok, I finally cleared this hurdle! The problem was that I didn’t have apache ant, and I didn’t have the correct path specified for the android sdk! The android project was created successfully and now I can go on with your tutorial :)

  • Seven

    I have a question that is so bothering me. how can I pass parameters like a user logging in to my database. can I use ms-sql database or sql light? If so how can I get the data from my sql server to the phone

    • Christophe Coenraets

      @Seven: You don’t connect your app to your remote database server. Instead, you expose a set of services (written in Java, PHP, Node, .NET, Rails, …) and your client app gets its data by invoking these services. If you want to store data locally, you use the SQLite database available on your device.

  • Filipe

    Great tutorial, came across it while doing a related search!

    I am having problems creating a phonegap 3.x app with Backbone.js + Require.js that uses the camera plugin. I keep on getting an error when trying start the camera, seems that the plugin is not loaded.

    Have you have any similar issues?

    • jason

      I have the same issues. how did you load the phonegap.js ? in index.html?

  • Matthew Reetz

    Testing on an iPhone 5s I am having an issue with the Employee ListView. If I click on the search box, then press delete, I get the full list of employees. I attempt to scroll to the bottom of the list but cannot. With a series of random touches I am able to get it to scroll to the bottom. Any ideas how to fix this?

  • Minor mistake in Part 11, Step 2, number 2. HomeView is referenced instead of EmployeeView.

    • Christophe Coenraets

      Good catch! Fixed. Thanks!

  • Pingback: PhoneGap 3.x Tutorial()

  • Mat Martin

    Hi Christoph – I am working through your tutorial and really like it. Have gotten stuck on stage 9. The employee search was working up to stage 8 (using handlebars templates).

    When I move the view to HomeView, the initial view renders properly, but then when I type in the search box, nothing happens (i.e., no employees appear).

    The error on javascript console is:

    Uncaught TypeError: Object .search-key has no method ‘apply’

    Which I think means this line in the initialise:

    this.el.on(‘keyup’, ‘.search-key’, this.findByName);

    isn’t working. I.e., its not finding an element in the DOM with the search-key class. But that plainly exists in index.html in the html template script block:

    Employee Directory

    If I change the child selector in the jQuery on call (e.g., to “.searc-key”), the error changes (to “.searc-key”) – so I’m reasonably sure that’s it.

    Can’t figure the rest of it out though.

    Any help appreciated!

    • Mat Martin

      Platform details: running the tutorial on chrome, debugging using developer tools. Also testing on a Galaxy S4 when the chrome tests pass.

    • Mat Martin

      Also getting the warning:
      event.returnValue is deprecated. Please use the standard event.preventDefault() instead.
      And Jquery version is: 1.9.1

      • San

        Mat, that is an internal issue with jQuery – you can see it in the console of just about every site

    • Christophe Coenraets

      Does Part 9’s solution work for you? It’s in www09.

      • Mat Martin

        Hi Christoph – I’m pretty sure I have verbatim the same code as you do in www09 (just looked at it on github). Everything was working fine up to part 8, and then the findByName stopped working in part 9.

      • Mat Martin

        On closer inspection, there was one small change which made the difference! I had the line:


        included immediately after the initialize() function definition. You had it after the render and findByName function definitions. That did it!

        Not sure why – but that’s probably because I’m new to javascript!

        BTW, I am really enjoying going through your tutorial. Its really well done.

        Perhaps in part 9, you could add a note to ensure that the ” this.initialize() ” is done after the findByName and render function definitions?



        • zeuz

          thank you very much, just had the same problem :)

        • Ben

          Same here, thanks for the fix mat!

        • Had the same problem, it worked! Although can’t understand the reason. It’ll be great if someone can explain ?

          • Leo Bergmann

            @ Mat Martin: Thanks for posting the solution, it really helped me!

            @ Nitin Surana: I’ll try to explain it as I understand it (although I could be wrong):

            The problem is, that the findByName function get’s called by a (keyboard) event that is added in the initialize function.
            The initialize function get’s called by this.initialize(); But if it hasn’t been initialized the findByName function tries to extract information that isn’t available yet.

            Hope it is understandable.

      • Adriana

        Hello Christophe!
        Thanks a lot for your tutorial! it’s great
        I’m stuck on part 9… there is nothing showing in my app after the changes I did in part 9…the this.initialize() is in the correct place, any idea?

        Thanks in advance!

  • Mat Martin

    Noticed the script block didn’t show in my post. The line in the block which defines the html for the search box is:

    Which plainly has the class search-key. Not sure why its not being found..

  • Mat Martin

    Apologies, angle brackets don’t work. Is there a way of posting literal code?

    Try single quotation marks:

  • Mat Martin

    Without angle brackets:

    input type=”search” placeholder=”search” class=”topcoat-search-input search-key”

  • Mat Martin


    I think part 11, step 2: “Define an initialize() function inside the HomeView constructor.”

    Should be rather: “Define an initialize() function inside the EmployeeView constructor.”

    I.e., HomeView ==> EmployeeView not in the code, but in the text (this is probably a separate typo to the one the other commenter mentions).

  • Mat Martin

    Just finished the tutorial. Thanks for putting this together – it was really fun to do and extremely useful.



    • Christophe Coenraets

      Thanks Mat. Glad to hear it was helpful.

  • Matthew Reetz

    The list view does not scroll to the bottom on a four inch iPhone with iOS 7. I’ve tested on device and simulator. Has anyone else had this issue?

  • Finally, Adobe is making amends for its sins by hiring people like you who want to educate. Now only if they reduce photoshop to about 299 pakistani rupees will i shift from pixlr.

  • kavin

    I am using ios 7 the navigator.notification.alert does not work fine, is thr any real issue with it,I followed the steps in the api docs.

  • Paul

    This is the clearest, most concise Phonegap tut I’ve ever read. You make it so easy! Thanks A MILLION!!

  • I’m trying to emulate android from the command line. But things are really slow. I recall reading somewhere that there are ways to get hardware acceleration enabled. How can I speed up my emulation of an android app built with this tutorial?

  • Making a mention of this .gitignore file might be useful for those that want to use version control

  • Héctor

    Christophe thank you very much.

  • part 11 step 2 sec 2: `Define an initialize() function inside the HomeView constructor.` should be `Define an initialize() function inside the EmployeeView constructor.`

  • Michael Oryl

    I see a problem in Part 9.

    This code in app.js doesn’t work for me:

    $(‘body’).html(new HomeView(adapter, homeTpl, employeeLiTpl).render().el);

    It throws an exception saying there is no “el” property available. “Uncaught TypeError: Cannot read property ‘el’ of undefined”

    Changing the code to three lines worked:

    var homeView = new HomeView(adapter, homeTpl, employeeLiTpl);

    • Michael Oryl

      It appears that I was missing the final “return this” in the HomeView.render() method. That caused the error.

  • Derek

    I’m was able to get the memory-adapter, websql-adapter and localstorage-adapter to work (shows list data). But when I used the jsonp-adapter the list is blank. What is going on… What can I do to investigate this? There is no error being reported… I’m using IOS and have tried in the emulator and in the device itself but the jsonp adapter seems to result in no errors but no data :(

    • Tinashe

      It appears the url for the json-adapter is returning an error. If you check the file there is and it’s not returning the list.

      {“error”:{“text”:SQLSTATE[HY000] [2003] Can’t connect to MySQL server on ‘’ (111)}}

    • Derek

      Actually when I run it in the chrome browser I see an error in the Console when using the jsonp-adapter…. The data adapter is getting initialized as I do see that the console reports that “Data adapter initialized”. But when I type a letter in the input — for example if I type “b” — then in the console I get an error. It is attempting to use the following URL to get the data (showing the text from the console):

      Resource interpreted as Script but transferred with MIME type text/html: “”.

      Then I get a RED line showing an error as follows:

      Uncaught SyntaxError: Unexpected token :

      ….So why am I getting an Uncaught SyntaxError?? What is the enexpected token??? What can do now???

      • Derek

        So when I type in the URL I showed above I get the same thing that someone else here has reported which is:

        {“error”:{“text”:SQLSTATE[HY000] [2003] Can’t connect to MySQL server on ‘’ (111)}}

        Not sure why it is mentioning

        Not sure if this is an irrelevant detail … maybe this URL only works in a JSONP context whatever that means exactly. Does that mean perhaps that the URL:

        … cannot by typed into a browser? Is this a correct URL?

        • Tinashe

 that’s local host. So the MySQL server associated with that URL is probably only listening to localhost which I guess you can’t really do anything about since you don’t own the server.

          • kevin

            Great tutorial!
            Got the same problem. No json data returned.

  • Pingback: PhoneGap for Hybrid App Development | Robin C Samuel()

  • EvanZ

    Thanks for doing this tutorial. Everything worked fine for me until I got to Step #8 and now I don’t see anything in the IOS emulator. Not sure what I’m doing wrong.

    • Jorge

      I am having the same issue. After step 8, when I write on the search field, nothing happens. The console says it doesn’t find cordova.js, but the file is where is supposed to be.

      • did you ever figure this out?

  • ramin

    Hi Christophe, first of all many thanks for the great tutorial. I went through all steps without a problem except the Part 12 (Location API). It works perfectly in the browser but nothing happens on my Android Nexus 4, Android 4.4.2.

    I know the plugin is setup correctly because if I look at the workshop app in the settings, it says the app uses the location services.

    I was wondering if you had any ideas why it’s not working.


    • ramin

      Well, problem was Google’s stupid policy that you have to let them track you, enabling the Location is not enough! Thanks a bunch though.

  • Itziar

    Thanks for the tutorial! It’s very useful.

  • Is it possible to build ios apps running ubuntu?

    I tried `cordova platforms add ios` but got the error:

    [Error: Xcode is (probably) not installed, specifically the command `xcodebuild` is unavailable or erroring out. Output of `xcodebuild -version` is: /bin/sh: 1: xcodebuild: not found

    Do I have to install xcode on my ubuntu system?

    • William Witt

      You can only build iOS apps on a Mac, fortunately allows you to build in the cloud. You still need all of the Apple issued certs in order to build and deploy.

  • Mario

    Hi there… great tutorial but i have a little problem. I’ve installed the camera & contact package from cordova but i always get an error in the ios emulator: “Contacts API not supported”. The location service works fine, but contacts and camera are not available.

    Do you have any ideas?

    • Same problem here. I’m been looking at the code all weekend and restarted from the beginning too many times to count and yet have the same issue as Mario. I want to introduce PhoneGap to my students in school but I need to understand it better first.

    • Hamid

      also same problem here!
      i used the example in camera plugin page on github and it works like a charm! but in this example camera and contact plugin does not work. i’ve tested with Samsung Galaxy Note 8 and HTC One.
      Thanks in advance

    • Hamid

      h have found the solution! it seems there was a conflict with fast click library. just remove it and camera plugin will work!

  • Bagara

    Hello and thanks for this excellent tutorial!

    I’m stuck in the step 11. When I click in “add location”, the app goes to the main page without notifying anything. But in the javascript console I get the error:
    “Uncaught TypeError: Object .add-location-btn has no method ‘apply'” (in chrome)
    “TypeError: i.handler.apply is not a function” (in firefox)

    I have copied and pasted all the code from above… where is the problem?

  • javaguy

    Hi Chris,

    Excellent tutorial and a great intro to phonegap.

    I’m a native developer (I do both iOS and Android) who once did W3, and I’ve come to take a look at how far PhoneGap has gotten since I left years ago for native.

    Quick question – how do you store state in the TopCoat navigation bar? The Navigation Bar doesn’t work correctly according to Apple Guidelines etc. and not even what I expect in the Android Activity stack.

    For example, if do the following: tap on John Williams -> James King and then tap back once, it should take me back to John Williams but instead end up on the home screen.

    Is there an easy way to do this in Single Page Apps architecture that is now prominent in PhoneGap? I realize that this is not a state / behaviour that is natural to HTTP based html sites…so I’m curious as to how + the best way to solve this problem in PhoneGap.


    • twork

      Just finished up with the tutorial, and have the same question about back functionality. Were you able to come up with a good solution? Thanks.

      • javaguy

        Sadly no…been busy unfortunately. Would be really good / important to add to this tutorial I think…the random Apple reviewer assigned to your app on submission could / would reject on this issue. I’ve been rejected for lesser offences

  • Shari

    I follow your instruction and i am getting bellow error message, Please let me know how to fix this error

    C:\AndroidDevelopment\development\pf>cordova platforms add android
    Creating android project…
    Error: An error occured during creation of android sub-project.


    throw e;
    Error: ERROR : executing command ‘ant’, make sure you have ant installed and add
    ed to your path.
    at C:\Users\Sname\.cordova\lib\android\cordova\3.3.0\bin\lib\check_reqs.j
    at ChildProcess.exithandler (child_process.js:641:7)
    at ChildProcess.EventEmitter.emit (events.js:98:17)
    at maybeClose (child_process.js:743:16)
    at Socket. (child_process.js:956:11)
    at Socket.EventEmitter.emit (events.js:95:17)
    at Pipe.close (net.js:466:12)

    at C:\Users\smohatad\AppData\Roaming\npm\node_modules\cordova\src\platform.j
    at ChildProcess.exithandler (child_process.js:641:7)
    at ChildProcess.EventEmitter.emit (events.js:98:17)
    at maybeClose (child_process.js:743:16)
    at Socket. (child_process.js:956:11)
    at Socket.EventEmitter.emit (events.js:95:17)
    at Pipe.close (net.js:466:12)

    • Shari

      I Figured it out

      This is what i did.
      1. download Ant and unzip at c:\ant
      2. find JDK in your system, If not install it . You should see a file like “JDK.6.0_27” my my case, You might have a different version
      3, download android SDK

      Open CMD prompt and do following

      1. c:\> set ANT_HOME = c:\ant
      2. c:\> set PATH=%PATH%;%ANT_HOME%\bin
      3. c:\> set JAVA_HOME = c:\jdk1.6.0_27
      4. C:\f>set PATH=%PATH%;;C:\AndroidDevelopment\adt-

      Once all these steps completed.
      Now run below command

      “cordova platforms add android”

      You should see a success message and Android is installed in your dir

  • Vinny M.

    Hey been looking at some of your tutorial for a while I think they’re thorough, I was wondering if you’d know how to add the facebook plugin? I’ve tried by adding the following line in the config.xml file :

    Then when I compile I get an error on line 698 of build.xml located in adt for android project I havent tried for ios. ? Have you ever had an issue integrating the facebook plugin ?


  • Wow, after a day of googling, I only find this tutorial is great. Others are either too old (written in 2012 or earlier) or too vogue. Thank you.

  • Christophe,

    Great tutorial, thanks for creating it.

    One question—is there a reason you use classes for identification of singular items, for example `.search-key`?

    It seems that ‘id’ would make more sense semantically, so I’m wondering if there’s a Cordova related reason.



  • David

    Hi Christophe,
    Thanks for this great tutorial.

  • Jorge

    I Part 5: Step 3 We see:

    When running on a device with the navigator.notification object available (the dialogs plugin is installed), override the window.alert() function and replace its default implementation with a call to navigator.notification.alert(). Add this code to the “Event Registration” block:

    document.addEventListener(‘deviceready’, function () {
    if (navigator.notification) { // Override default HTML alert with native dialog
    window.alert = function (message) {
    message, // message
    null, // callback
    “Workshop”, // title
    ‘OK’ // buttonName
    }, false);

    Where is this code located?? In which file I am supposed to modify that??

    • duedl0r


      • jery

        Excellent tutorial.

        I have got a problem when i try to add the code block into the “Event Registration “block. there is no response affter i added those code.

        the “Event Retistration” block is like the following:
        /* ——————————— Event Registration ——————————– */
        $(‘.search-key’).on(‘keyup’, findByName);
        $(‘.help-btn’).on(‘click’, function() {
        // alert(“Employee Directory v3.4”);
        document.addEventListener(‘deviceready’, function () {
        if (navigator.notification) { // Override default HTML alert with native dialog
        window.alert = function (message) {
        message, // message
        null, // callback
        “Workshop”, // title
        ‘OK’ // buttonName
        }, false);

        could you tell me how to fix it?

  • Tristan


    This guide has been great, thank you. Where would I change the database location for connecting a mongodb with nodejs to an external mongodb (not on localhost)?

    I cannot for the life of me work out where to put the database/username/password information but the app works great as localhost.

    Many thanks in advance.

  • Brad

    Yeah! This tutorial totally rocks for cordova hello world x10… Super thank you!

  • Dawesi

    Use Sencha and you’ll save yourself a tonne of work. Nice article tho.

  • Hi!
    Thanks for a great series.
    I’ve got a few questions: which of your versions has the best response (closest to NATIVE)
    what has better performance angular js VS backbone js ?


  • Sani Elfishawy

    Great tutorial thanks!

    Do you know whether you use the cordova CLI to build with a particular (post 3.0) version of Cordova?

    cordova create …
    cordova platform add …

    seems to add the most recent version of cordova framework. Currently 3.4.0. What if you wanted to build with 3.1.0 for example?

  • LA

    Just wanted to THANK YOU for this tutorial. Extremely helpful.

  • Alberto Lopez

    Hello Christophe,

    I have one question, I hope you could help me giving me some advice, what would you do if you were required to authenticate access to this app?

    Alberto Lopez

  • Sam

    Thank you so much for this. Straight to the point and very informative, you may have saved me from going insane! Thanks again.

  • Hi, I don’t have an app.js file, I ma using cordova 3. Any thoughts ?

    • codexmonkey


  • Excellent tutorial – excellent. I get api not supported on the camera and contacts – at the very end but everything else works amazingly. deployed to kit kat phone – not sure but I’ll keep trying to figure it out.

    • Hamid

      also same problem here!
      i used the example in camera plugin page on github and it works like a charm! but in this example camera and contact plugin does not work. i’ve tested with Samsung Galaxy Note 8 and HTC One.
      Thanks in advance

    • Hamid

      h have found the solution! it seems there was a conflict with fast click library. just remove it and camera plugin will work!

  • I think I figured it out – by default – this line in the config.xml says cordova… not phonegap..
    updated to…


    plus added to config file….

  • linda


    First of all, it’s a very good tutorial.
    Even for people who doesn’t speak english, is easy to understand.
    However, i’m trying to switch to ‘JSONPAdapter’ and i’m having problems, it doesn’t work :(

    When I test in a navigator, it blocked by a script…

    And in the phone, it doesn’t show anything…

    Any idea?

  • Mark

    Awesome tutorial!

  • Alejandro

    First at all, congratulations. I have a very rare issue. I can’t execute any plugin inside the route() function after a hash chage. There is no error, it just skips the window var. For example, I have inAppBrowser installed. If I run on the first steep of the route() function, it works. If I change hash and execute again the it doesn’t do anything. It also happends with the console.log, etc…

    any help?

  • Carlos Garcia

    I’m having the same problem as other people here: when I try to use the JSONPAdapter, the list won’t show up. I tried setting up a local json file (although I might be doing it wrong, since I’m new to json) but it’s still not showing up any data. Any help here?

  • ttemp

    great tutorial :) I spend like 2 days searching for something good enough to start with this is great :)

    one thing though i really think you should add all the phonegap build quirks (config.xml needs to change to give permissions to camera and contacts and geolocation) moreover there are some updates ( contacts api need to be rewriten by and so does geolocation at least for galaxy s2)

    thanks this is really great

  • Rada

    I got a problem with JSONPAdapter. Anyone have a solution?

  • Chris

    Thanks Christophe for this great tutorial. You just unlocked a lot of doors for me

  • This electric mixer works very well and measures
    about 3 x 3 x 14 inches. No should decant it bit by bit right into a blender jug then into another container.

    With the simplicity of use, also comes a design which is
    meant for comfortable usage.

  • Steve James

    Hi Christophe,

    Greaqt titorial,

    I have a problem however, whilst adding android platform I get the following error:
    Error ENOENT, no such file or directory C:|users\Dell\.cordova\lib\android\cordova\3.4.0\VERSION

    It is true that this directory doesn’t exist, but then I didn’t create the rest of the structure, I just followed the instructions so I don’t know why or how this should exist.

    All help appreciated.


    • Steve James

      Have sorted it.
      I reloaded cordova several times but it was only when I deleted the install and reloaded it that the problem cease. In the meantime, I loaded JDK and ANT. Not sure if these had any effect but would have expected different errors if they were the problem. I already had ADT Eclipse loaded BTW.

  • Great tutorial!

    I followed the tutorial and sometimes stuck in one place and didn’t know why. Google online and find debug in chrome is very useful:


  • Safaa Alnablsi

    I’ve finished the tutorial , thank you very much for this great effort :)
    everything worked perfectly with me, but I have a few questions:
    I want to make a setting page with two text boxes and save button
    problem is I can’t slide to home after clicking the save because route function is written in app.js
    and the rout method depends on hash, so home & setting would be the same.
    can you help me on that ? I can’t find any useful tutorial except yours .. and I ad build my app on yours

  • I pay a visit every day a few sites and sites to read content, but this website
    offers feature based content.

  • Sumit

    A great tutorial.

    But i need to create a splash screen for android application like facebook application. How can i implement this in AngularJS using ionic framework. Please help me out.

    Thanx in advance.

  • Nice tutorial so far, but… At step 8 my screen stays blank, both on my device (Samsung) and emulator. Can’t get it to compile the home and employee list templates in any way. I have everything installed on openSUSE (following Ubuntu guidelines).

    Some other folks had the same problem, but I never saw a resolution.

    Also, it would be nice to know how to debug, so that I’d have a chance of sorting out problems…


  • Hi.. i want just say thanks…

  • Why not port the scanner into the internet and City Corridor so they will know when you arrive dwelling as properly when and exactly where you ride. Sooner or later…

  • Rendy

    I build windows phone app version 8 with cordova 3.4.1, i want to ask how to cordova to get data api from my own website? thanks. Does cordova support ajax jquery? And the last, why i can’t use input type text?

  • User123

    Thank you very much for the tutorial!

  • Harry

    Thanks for the tutorial! Sorry for reviving an old blog post. However, I can’t seem to find any reference in handlebars.js documentation for your use of “{{#.}}” and “{{/.}}” block expression syntax. What is it?

    The only thing I could find is blockHelperMissing helper in handlebars.js that defaults to ‘each’ way inside the code.

    So are you using the ‘dot’ as a random string along the lines of “HERE docs” in other languages.

    • Hi Harry, I was also wondering about that reference. I figured it may have been jQuery short hand for a ‘for each’ loop or something along those lines. Did you manage to find anything as i still haven’t found a definitive answer?

  • Ottawa Senators Black discount hockey coupon code

  • Pingback: Making An App (Industry Student Project) Day 03 | T Ratnayake()

  • Hello! I could have sworn I’ve visited this blog before but after browsing through some
    of the posts I realized it’s new to me. Regardless, I’m certainly pleased I discovered it and I’ll be book-marking it and checking back frequently!

  • Shashikant Kumar

    How to Implement file (pdf/ppt) downloading from server using phone-gap with ionic framework ?

  • Tad

    Thank you, Christophe. Great tutorial. I got hung up a bit from time to time but figured them all out. The worst was this “android” emulation issue which really stumped me for a while.

    WARNING : no emulator specified, defaulting to my_avd
    Waiting for emulator…
    emulator: ERROR: This AVD’s configuration is missing a kernel file!!

    Turns out there are a few possible causes but in my case the issue was that no emulation environment had been created. You need to run the AVD management tool:

    android avd

    from a command line in the Mac. Create devices of choice and this is apparently creates the “kernel” file.

  • Greg

    Great tutorial. Very easy to follow and covers a multitude of areas including JS, Node, template, project structure and last but not least is PhoneGap. Thanks Christophe, this really helped me get up to speed on several areas at once.

  • Perhaps you have used by getting the Crazy shirts Coupon Code just to
    recognize that you can not utilize this less costly it supplies?
    Anyone whom suppliers on the net straightforward Crazy shirts Coupon Code would certainly’ve expert
    this trouble. These sort of Crazy shirts Coupon Code will normally be really valued just by
    internet buyers considering that they make them
    become issues aside from expertise describing relevant revenues.

    You can avoid virtually any kind of problems along with using a
    Crazy shirts Coupon Code has to you understand they will
    to make essential strategies rather than they will.

    A lot of the problems totally consumed with the support of customers contain:.

    Obtaining the done Crazy shirts Coupon Code: The majority of Crazy shirts Coupon Code use an event time-frame throughout that they might stop made
    use of to acquire a much more budget-friendly cost
    or merely just handy approach. Together, an added person rather back might acquire fortuitous utilizing your
    Crazy shirts Coupon Code which include passed her expiration day when your company have
    really never deactivated this sort of reduction.

    Not essentially checking out the Crazy shirts
    Coupon Code totally. Before choosing to what specifically sort of Crazy shirts Coupon Code must be used
    any person efficiently could well aren’t thrilled to discovered find the
    most from taking advantage of. You could not believe basically all Crazy shirts Coupon Code offer a developed lower.

    Going down getting a certain Crazy shirts Coupon Code.
    On the other hand, you can use software program applications keep to the real Crazy shirts Coupon Code so that you could use them even with
    the truth that vital.

    You could have a massive quantity terrific deals of cash on a regular
    regular monthly basis using the appropriate Crazy shirts Coupon
    Code when you are obtaining online. Acquiring this type of Crazy shirts Coupon Code could not be uncomplicated.
    Have to be fact, you’re likely to be investing lots
    of impartial looking for individuals Crazy shirts Coupon Code.

    You need to recognize making use of Crazy shirts Coupon Code in the accountable
    approach or probably you carry out uncover youself to acquire spending
    a more substantial expense for any individual opportunities.
    It does not produce just considering that to recognize a rather a ton of elements being made easily
    supplied with a little asking cost as a result of Crazy shirts Coupon Code.

    Possibly you have made use of by acquiring the Crazy shirts Coupon Code simply to recognize that you can not use
    this even more economical it provides? Given that they make them come to be issues and also
    proficiency associating with pertinent revenues, these kinds of Crazy shirts Coupon Code will frequently be
    extremely cherished simply by net customers.

    Getting the done Crazy shirts Coupon Code: Most Crazy
    shirts Coupon Code use a celebration time-frame all over that
    they could stop made use of to get a much more budget-friendly
    expense or simply simply useful technique. Before choosing to
    exactly what especially kind of Crazy shirts Coupon Code must be used anybody effectively could well
    aren’t thrilled to discovered locate the most from using.

    Perhaps you have made use of by acquiring the Crazy shirts Coupon Code just to identify that you can not utilize
    this cheaper it gives? These types of Crazy shirts Coupon Code will
    typically be exceptionally valued just by net customers considering that
    they make them wind up being troubles together with knowledge referring to essential revenues.

    Prior to opting to exactly what exactly kind of Crazy shirts Coupon
    Code need to be taken advantage of anyone successfully could well
    aren’t thrilled to found out discover the most from using.
    You could have a large quantity wonderful bargains of cash on a routine month-to-month basis taking advantage
    of the right Crazy shirts Coupon Code when you are obtaining online.

    Perhaps you have used by obtaining the Crazy shirts Coupon Code just to acknowledge that you can not utilize this less expensive it offers?
    These kinds of Crazy shirts Coupon Code will usually be extremely valued merely by web buyers considering that they make them end up being issues in addition to knowledge referring to relevant revenues.

    Prior to picking to just what specifically kind of Crazy shirts Coupon Code
    need to be made use of any sort of individual effectively can
    well aren’t thrilled to discovered find the most from making usage of.
    When you are acquiring online, you could have a massive amount wonderful deals of money on a
    regular month-to-month basis making use of the best Crazy
    shirts Coupon Code.

  • sir

    first time with Cordova, how to import the project in eclipse after cloning it? thanks

    • Phu

      Do this : file – new project – android – android project from existing code – click next – in root directory browse to the phonegap app that you created open platforms then android and click on

  • The sign that the intelli-clean does not work is that when you press the intelli-clean button on the handle,
    there is no difference if it is on or off, it
    does not change suction. Although the low price of many steam cleaners may seem enticing, it is important to consider
    the quality of the machine. For bagless vacuum machines,
    check the compartment where dust is stored.

  • Adel Haghjoo arbetar som kirurg på kliniken . Adel Haghjoo specialist i allmänkirurgi arbetar på kliniken och har vårdavtal med.

  • Intyg: Vi utför olika typer av intyg som körkortsintyg , friskintyg för utbildning i Sverige och utomlands , friskintyg för arbete , friskintyg för.

  • jignesh

    hi , working on the notification. when i am in browser it show alert.
    but when am in antoher application or in main screen cant not see the notification of native of android.
    app is running in background.

  • It utilises in game graphics and the game scenery to create a consistent look and cleverly alters camera
    angles and utilises editing. Buying and sending mobile phones onlibe iis
    very much plausible as you get the best of offers and brands
    such as, Blackberry, Apple, LG, Sony Ericsson, etc. If someone is looking to change their mobile phone
    then this is a best chance for him because offers on mobile phones are
    going on due to festival season.

  • obviously like your website but you have to check the spelling on several of your posts. Many of them are rife with spelling problems and I to find it very troublesome to tell the reality on the other hand I will certainly come back again.

  • DeveloperJoe

    Hi, it would be nice to show to the public an alternative way to develop the phonegap application. Without connecting to any remote host – just locally. It was possible before – seems gone right now. Everyone is forcing to use the CLI way which is downloading a lot of staff from remote hosts. What about just to prepare The Offline Basic Template?

  • Tea Tree oil iis a homeopathic item to have on hand at all
    times, and can be used for mahy different conditions.
    Cervical smears are thhe best safeguard against cervical cancer.
    Not everyone will be receptive to the methods that are discussed.

  • I’ve read some excellent stuff here. Certainly worth bookmarking for revisiting.
    I wonder how much attempt you place to create one
    of these fantastic informative site.

  • Useful information. Fortunate me I found your web site accidentally,
    and I’m stunned why this accident didn’t took place in
    advance! I bookmarked it.

  • Swapna

    Hi, Thanks a lot for the tutorial. I tried running this example but i get this error ,

    ERROR: module cordova/exec/proxy not found on line 0 for undefined

    I am trying it in jboss dev studio with Cordova support. I have the Android sdk platform, ant , Phonegap 3.3 version. So when i run this project in the Jboss CordovaSim i get this error. Looks like when the Cordova plugins are referred this error is thrown? is there anything else i need to take care of ?


  • Paul Schreuder

    Hi Christophe,

    Awesome tutorial, which has given me a great insight int Cordova . Phonegap. Thank you to all the others that posted issues and challenges as these helped resolve many issues I also experienced.


  • Trevor Best

    Great tutorial, but should you not be using indexedDB rather than websql given that the latter was deprecated? I’ve used the polyfill ( shim on iOS to great effect as that platform doesn’t yet support it.

  • Wonderful beat ! I wish to apprentice at the same time as you amend your site,
    how can i subscribe for a weblog website? The account helped me a
    applicable deal. I had been a little bit acquainted of this your broadcast
    offered vivid transparent idea

  • Wow! This can be one particular of the most useful blogs We
    have ever arrive across on this subject. Basically Magnificent.
    I’m also an expert in this topic therefore I can understand your effort.

  • Felipe

    Hi Christophe,

    Thanks for the tutorial. By using it I was able to build my own app =).

    However I’m having an issue with high memory usage. My app uses about the same memory as the one presented here, which I think is pretty high.

    Both starts with about 50mb in my nexus 4 and go up to 70mb (I’ve used phonegap build service to build them).

    Is that a normal thing with phonegap?

  • Pingback: Building a Native Mobile App with Phonegap and jQuery Mobile 1.4 |

  • Lomas Joshi

    Hello Christophe,
    I have successfully developed android app using phonegap. But i wonder if i can develop widget for the application? If this is the wrong place for this question, please suggest me where can get the correct answer for it.

  • Pingback: Tutorial sobre phonegap-cordova - formandomeformandome()

  • designer

    What’s the point of the Local Storage options?
    It is intended to store data in the application (in the mobile device) so it doesn’t have to do the json request each time the application starts?
    In which situation I would need each of these adapters?

  • You are my intake, I possess few web logs and occasionally run out from brand :). “The soul that is within me no man can degrade.” by Frederick Douglas.

  • I am a coder and I’ve just come up with a brand-new social
    networking site. I’m just seeking out beta evaluators to surf and try it out.
    Do you need to opt-in? We’re going to compensate

  • Great

  • Hello to every body, it’s my first visit of
    this webpage; this web site includes amazing and really excellent stuff in support of readers.

  • Greetings from Carolina! I

  • The high graphic games that we play on our computer are all efforts of these teams and organizations.
    Internet has been offering online games ranging from flash
    to Java ones and many more. This game has to get a rating 4 out of 5
    for a retro experience with a modern twist.

  • Pingback: APP#1: Stream music tracks from soundcloud using Cordova (Phonegap 3.x) | MythLab()

  • Yoou know sometimes people can be doubly encouraged to go to your website or
    make troops them request for more information through phone or by replying to your mail.
    Running a successful troops direct mailing is your ultimate goal.

  • The long-drawn negotiations with orlando taxi companies the federal government
    is allowed to do. Mike Granatt becomes one of a few
    slight differences all applicable taxi regulations are pretty much the way it used to be
    with him. You can’t be me. I mean, come on, Elaine, I’m talking one round, man, I was driving
    in my Action Burger truck. You know I love cowboys.

    To learn your way around. No, I’m just waiting for a call on our phone number.

  • * A sitemap to navigate your website is helpful for visitors to access main pages.
    But unfortunately not every request will get approved.

    You need to make your potential customers aware
    of your products and services to ensure that they recognize them as valid solutions to their
    everyday problems.

  • hungryguy

    Welcome. Could someone after working guide insert code or files. index.php employeViews.js and app.js? Very need this. Thanks in advance.

  • Max

    Hi everyone i have a problem in the part 2 when i choose to emulate or run Platform android cmd sent a error which is :
    Error code 1 for command:cmd with args /s,/c,ant,debug,-f,C:Users\Maxime\Desktop\Sites\Cordova\platforms\android\build.xml,-Dout.dir=ant-build,-Dgen.absolute.dir=ant_gen

    Error: C:\Users\Maxime\Desktop\Sites\Cordova\workshop\platforms\android\cordova\run.bat: Command failed with exit code 8
    at ChildProcess.whenDone (C:\Users\Maxime\AppData\Roaming\npm\node_modules\c
    at ChildProcess.emit (events.js:98:17)
    at maybeClose (child_process.js:755:16)
    at Process.ChildProcess._handle.onexit (child_process.js:822:5)

    • Max

      Can you help me plz ? Thank you .

  • hungryguy

    Can anyone give me the codes ready application? I’m very concerned about this

  • “wow, awesome blog post.Thanks Again. Cool.”

  • ready app

    Welcome. I need a ready-made applications toutrial. Can someone paste the code of the application?

  • I have to thank you for the efforts you have put in penning this website.
    I am hoping to view the same high-grade content from you in the future as well.
    In fact, your creative writing abilities has motivated me to get my own, personal
    blog now ;)

  • No one routes for the evil villan who’s run off with the hero’s beau, same
    applies to a site that’s been stuck in Google’s naughty corner.

    These pre-computed numbers, hold on in a very giant
    information bank for millions or URLs on the net. You need to make your potential customers aware of your products and services to ensure
    that they recognize them as valid solutions to their everyday problems.

  • barcodescanner

    Hello, I need help. I want to add a button barcodescanner applications. Unfortunately, I do not know how to do it, could someone help me? This plugin is already installed in the workshop.

  • Tod

    If some one wishes to be updated with newest technologies after that he
    must be visit this website and be up to date daily.

  • Greetings from Ohio! I’m bored to death at work so I decided to
    check out your blog on my iphone during lunch break.
    I really like the info you present here and can’t wait to take a look when I get home.
    I’m amazed at how fast your blog loaded on my phone ..
    I’m not even using WIFI, just 3G .. Anyhow, excellent site!

  • Antonio

    Hi, great tutorial.
    One question:

    I don’t find the folder workshop/js/adapters

  • Help in:
    Part 7 – SubPart 3
    Modify the data adapter initialization logic: when the adapter has been successfully initialized, call the renderHomeView() function to programmatically display the Home View.

    Where should i find the data adapter initialisation ?

  • It’s in fact very complicated in this busy life to listen news on Television, therefore I only use world wide web for that reason, and get the most up-to-date news.

  • Post incroyablement cultivant

  • I’m gone to tell my little brother, that he should also pay a visit this webpage
    on regular basis to take updated from hottest information.

  • Pingback: Cordova (aka PhoneGap) 3.x Tutorial | Christophe Coenraets |()

  • I have read some good stuff here. Certainly value bookmarking for revisiting.
    I wonder how much effort you place to make the sort of magnificent informative website.

  • Hither are tips to assistance you leverage licensed software programs online at a cost
    that is a great deal to a lesser extent than the
    suggested retail terms. You’ll besides ascertain some useful sites that provide
    first-class deals on pop software titles.

  • We have been demanding a return phone calls that high taxes are your obligations.
    I mean, the amount of roofs provide whether or not.
    If you are planning to sell your home and the particular
    scope in the business. Access to clean your basement, and producing of additionally harm towards
    the sewages. For the obvious quality of the renewal sale.
    Success is entirely your own GC, you’ll
    have peace of mind.

  • Pingback: Zur ersten eigenen Android App - Stefan Wilhelm Info()

  • Fjito

    I find this tutorial very helpful. However, I got stuck on Part 4.
    “Open the following files in workshop/js/adapters, and explore the different persistence adapters:”

    I followed every step but I dont have any js/adapters folder neither do I have any of the js files mentioned, like “memory-adapter.js” in my Project. What could I have done wrong?

  • wow, nice and helpful, when this kind of workshop event will be in U.A.E :(

  • Vishal

    If you are wondering on Part 4 (as i was), there’s a new tutorial which follows new file structure in tutorial.

  • Vishal

    If you are wondering on Part 4 (as i was), there’s a new tutorial which follows new file structure(in github repository) in tutorial.

  • Ahmed

    In Part 4: Choosing a Local Storage Option
    I cann’t find those files workshop/js/adapters
    Please help

  • Pingback: Fix Homeview.js Errors - Windows XP, Vista, 7 & 8()

  • dheeraj

    how ca i add custome plug in to my cordova application.
    i’m having .java and .js file but unable to implement it to my code.

  • Pingback: Salesforce Connected App OAuth Process in Hybrid Mobile Application - DL-UAT()

  • gary cahill

    How do you integrate the cordova camera API with ionic so (without a button event) I can automatically load the getPicture function (and interface) with additional UI buttons on it.

  • unknown

    $cordova platform add android….
    showing error as command failed with exit code ENOENT

  • if please post how we can do cordova, php, mysql, json together, Need one example please.

  • Pingback: Which UI to use for Cordova Android/iPhone app development [closed] - TecHub()

  • ali

    Why applications built with cordova do not play back video and audio?

  • Mathandos

    Hi, as a first time mobile developer I followed the tutorial step by step, but I don’t know where the hiccup was because I failed to get the app running on both the emulator and browser. Any assistance to get it up and running would be greatly appreciated

  • Pingback: How do I get started with Android application development with only a very basic knowledge about programming? | Govtemp Diary's()

  • Antonius Sulistyo

    I followed this tutorial step by step but had to stop up to two command lines below

    1. cordova plugin add org.apache.cordova.device
    2. cordova plugin add org.apache.cordova.console

    I am new to Cordova and have no idea how to proceed with the following errors

    cmd: Command failed with exit code 1 Output error:
    npm ERR! code E404
    npm ERR! 404 Not found: org.apache.cordova.device
    npm ERR! 404
    npm ERR! 404 ‘org.apache.cordova.device’ is not in the npm registry.
    npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
    npm ERR! 404
    npm ERR! 404 Note that you can also install from a
    npm ERR! 404 tarball, folder, http url, or git url.

    I hope for help from those who understand Cordova Technology how to overcome this problem