Cordova (aka PhoneGap) 3.x Tutorial

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

cordova

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).

Requirements:

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


iOS

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

Android

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) {
                navigator.notification.alert(
                    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.

    FastClick.attach(document.body);
  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>";
        $('body').html(html);
        $('.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 () {
        renderHomeView();
    });
    
  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>
        </div>
        <div class="search-bar">
            <input type="search" placeholder="search" class="topcoat-search-input search-key">
        </div>
        <div class="topcoat-list__container">
            <ul class="topcoat-list list employee-list"></ul>
        </div>
    </script>
    
  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>
                <p>{{title}}</p>
                <span class="chevron"></span><span class="count">{{reports}}</span>
            </a>
        </li>
        {{/.}}
    </script>
    
  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() {
        $('body').html(homeTpl());
        $('.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) {
            $('.employee-list').html(employeeLiTpl(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);
        };
    
        this.initialize();
    
    }
    
  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() {
        this.el.html(template());
        return this;
    };
    
  5. Move the findByName() function from app.js to HomeView.
    this.findByName = function() {
        adapter.findByName($('.search-key').val()).done(function(employees) {
            $('.employee-list').html(listItemTemplate(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>
    </div>
    
  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>
            </a>
        </div>
        <div class="topcoat-navigation-bar__item center half">
            <h1 class="topcoat-navigation-bar__title">Employee</h1>
        </div>
    </div>
    <div class='details'>
        <img src="assets/pics/{{pic}}" class="employee-image">
        <h1>{{firstName}} {{lastName}}</h1>
        <h2>{{title}}</h2>
        <h2>{{city}}</h2>
        <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>
                {{/if}}
                <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>
            </ul>
        </div>
    </div>
</script>

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/>');
        };
    
        this.initialize();
    
    }
    
  3. Define a render() function implemented as follows:
    this.render = function() {
        this.el.html(template(employee));
        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);
            return;
        }
        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 () {
        route();
    });
    
  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) {
        event.preventDefault();
        navigator.geolocation.getCurrentPosition(
            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) {
        event.preventDefault();
        console.log('addToContacts');
        if (!navigator.contacts) {
            alert("Contacts API not supported", "Error");
            return;
        }
        var contact = navigator.contacts.create();
        contact.name = {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;
        contact.save();
        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 org.apache.cordova.camera
  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) {
        event.preventDefault();
        if (!navigator.camera) {
            alert("Camera API not supported", "Error");
            return;
        }
        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
                        };
    
        navigator.camera.getPicture(
            function(imageData) {
                $('.employee-image', this.el).attr('src', "data:image/jpeg;base64," + imageData);
            },
            function() {
                alert('Error taking picture', 'Error');
            },
            options);
    
        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);
    

    and

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


Part 16: Explore Other Implementations


200 Responses to Cordova (aka PhoneGap) 3.x Tutorial

  1. suraj kumar gorai January 8, 2014 at 11:59 pm #

    Thanks Christophe,

    I search these type tutorial from long time.

    • anupam April 29, 2014 at 2:11 am #

      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

  2. Tiendq January 9, 2014 at 5:27 am #

    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?

    Thanks,

  3. Qian January 9, 2014 at 9:11 am #

    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!

  4. Christophe Coenraets January 9, 2014 at 11:14 am #

    @Tiendq.
    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 April 29, 2014 at 2:12 am #

      It is very help full for beginners thanks a lot sir

      can you send me a zip folder for more help

  5. Christophe Coenraets January 9, 2014 at 11:23 am #

    @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)

    • José Jesús Pérez Rivas March 12, 2014 at 8:02 am #

      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.

  6. Ocean Lin January 9, 2014 at 11:54 am #

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

  7. Hernan January 9, 2014 at 2:04 pm #

    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 January 22, 2014 at 2:48 am #

      I’m having the same problem.

      How did you solve it Hernan?

      • michas March 4, 2014 at 10:21 am #

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

    • Michael Oryl February 1, 2014 at 9:55 am #

      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:

      .list,
      .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 February 1, 2014 at 9:56 am #

        It would look like this:

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

        • Ben April 26, 2014 at 8:29 pm #

          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 May 27, 2014 at 3:40 am #

            It works for me
            Thanks

  8. Ross Martin January 10, 2014 at 10:08 am #

    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 January 16, 2014 at 9:58 am #

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

  9. Geovane January 13, 2014 at 10:26 am #

    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!

  10. ahetman January 13, 2014 at 4:33 pm #

    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…

    C:\Users\Andrei\AppData\Roaming\npm\node_modules\cordova\node_modules\q\q.js:126

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

    C:\Users\Andrei\.cordova\lib\android\cordova\3.3.0\bin\node_modules\q\q.js:126
    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:
    47:27
    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:
    244:30
    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?

    • ahetman January 13, 2014 at 4:39 pm #

      additionally, for ios i get:

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

      C:\Users\Andrei\AppData\Roaming\npm\node_modules\cordova\node_modules\q\q.js:126

      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:
      244:30
      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 :)

      • ahetman January 14, 2014 at 4:58 pm #

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

    • ahetman January 14, 2014 at 6:00 pm #

      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 :)

  11. Seven January 15, 2014 at 10:54 am #

    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 January 16, 2014 at 9:03 am #

      @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.

  12. Filipe January 16, 2014 at 11:39 am #

    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 June 17, 2014 at 8:48 am #

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

  13. Matthew Reetz January 16, 2014 at 3:02 pm #

    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?

  14. ahetman January 16, 2014 at 6:50 pm #

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

    • Christophe Coenraets January 16, 2014 at 10:48 pm #

      Good catch! Fixed. Thanks!

  15. Mat Martin January 17, 2014 at 6:22 am #

    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 January 17, 2014 at 7:15 am #

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

    • Mat Martin January 17, 2014 at 7:21 am #

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

      • San April 10, 2014 at 4:51 pm #

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

    • Christophe Coenraets January 17, 2014 at 8:05 am #

      Matt,
      Does Part 9′s solution work for you? It’s in www09.
      Christophe

      • Mat Martin January 17, 2014 at 8:45 am #

        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 January 17, 2014 at 8:52 am #

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

        this.initialize();

        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?

        cheers

        Mat

        • zeuz February 26, 2014 at 10:06 am #

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

        • Ben March 2, 2014 at 8:33 am #

          Same here, thanks for the fix mat!

        • Nitin Surana March 17, 2014 at 10:37 pm #

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

          • Leo Bergmann August 8, 2014 at 12:24 pm #

            @ 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 March 9, 2014 at 11:03 pm #

        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!

  16. Mat Martin January 17, 2014 at 6:24 am #

    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..

  17. Mat Martin January 17, 2014 at 6:26 am #

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

    Try single quotation marks:

  18. Mat Martin January 17, 2014 at 6:27 am #

    Without angle brackets:

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

  19. Mat Martin January 17, 2014 at 9:20 am #

    Typo?

    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).

  20. Mat Martin January 17, 2014 at 10:12 am #

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

    cheers

    Mat

    • Christophe Coenraets January 17, 2014 at 10:35 am #

      Thanks Mat. Glad to hear it was helpful.

  21. Matthew Reetz January 20, 2014 at 9:02 am #

    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?

  22. Satya January 24, 2014 at 2:05 pm #

    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.

  23. kavin January 25, 2014 at 6:52 am #

    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 pahonegap.com api docs.

  24. Paul January 27, 2014 at 2:07 pm #

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

  25. Harry Moreno January 27, 2014 at 2:49 pm #

    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?

  26. Harry Moreno January 27, 2014 at 3:30 pm #

    Making a mention of this .gitignore file https://github.com/morenoh149/cordova-employee-app/blob/master/.gitignore might be useful for those that want to use version control

  27. Héctor January 27, 2014 at 6:21 pm #

    Christophe thank you very much.

  28. Harry Moreno January 27, 2014 at 10:06 pm #

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

  29. Michael Oryl January 29, 2014 at 12:53 pm #

    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);
    homeView.render();
    $(‘body’).html(homeView.el);

    • Michael Oryl January 30, 2014 at 12:19 pm #

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

  30. Derek January 29, 2014 at 1:22 pm #

    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 January 29, 2014 at 2:40 pm #

      It appears the url for the json-adapter is returning an error. If you check the file there is
      http://coenraets.org/directory/api/employees and it’s not returning the list.

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

    • Derek January 29, 2014 at 4:00 pm #

      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: “http://coenraets.org/directory/api/employees?name=b&callback=jQuery191018584011192433536_1391028714970&_=1391028714971″.

      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 January 29, 2014 at 4:06 pm #

        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 ’127.0.0.1′ (111)}}

        Not sure why it is mentioning 127.0.0.1.

        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:

        http://coenraets.org/directory/api/employees?name=b&callback=jQuery191018584011192433536_1391028714970&_=1391028714971

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

        • Tinashe January 29, 2014 at 6:12 pm #

          127.0.0.1 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 February 4, 2014 at 9:52 am #

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

  31. EvanZ February 1, 2014 at 12:02 pm #

    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 February 20, 2014 at 5:32 pm #

      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.

      • Satjot September 10, 2014 at 7:27 pm #

        did you ever figure this out?

  32. ramin February 4, 2014 at 10:49 pm #

    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.

    Cheers,
    Ramin

    • ramin February 5, 2014 at 6:13 pm #

      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.

  33. Itziar February 5, 2014 at 4:46 am #

    Thanks for the tutorial! It’s very useful.

  34. connor February 7, 2014 at 4:28 am #

    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 February 9, 2014 at 11:10 pm #

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

  35. Mario February 10, 2014 at 3:28 am #

    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?

    • Rick February 10, 2014 at 5:08 pm #

      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 May 29, 2014 at 7:38 am #

      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 May 30, 2014 at 7:26 am #

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

  36. Bagara February 10, 2014 at 11:02 am #

    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?

  37. javaguy February 11, 2014 at 12:13 pm #

    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.

    Thanks

    • twork March 12, 2014 at 7:53 pm #

      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 March 14, 2014 at 6:12 am #

        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

  38. Shari February 11, 2014 at 7:06 pm #

    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.

    C:\Users\Sname\.cordova\lib\android\cordova\3.3.0\bin\node_modules\q\q.js:126

    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
    s:47:27
    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
    s:282:30
    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 February 11, 2014 at 8:48 pm #

      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-
      bundle-windows-x86_64-20131030\sdk\platform-tools;C:\AndroidDevelopment\adt-bund
      le-windows-x86_64-20131030\sdk\tools

      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

  39. Vinny M. February 12, 2014 at 8:29 pm #

    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 ?

    Cheers,

  40. ospider February 14, 2014 at 1:42 am #

    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.

  41. Rod Knowlton February 19, 2014 at 4:15 pm #

    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.

    Thanks,

    Rod

  42. David February 20, 2014 at 2:47 am #

    Hi Christophe,
    Thanks for this great tutorial.

  43. Jorge February 20, 2014 at 11:08 am #

    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) {
    navigator.notification.alert(
    message, // message
    null, // callback
    “Workshop”, // title
    ‘OK’ // buttonName
    );
    };
    }
    }, false);

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

    • duedl0r March 24, 2014 at 12:56 pm #

      app.js

  44. Tristan February 25, 2014 at 4:45 pm #

    Hi,

    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.
    Tristan

  45. Brad February 25, 2014 at 4:58 pm #

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

  46. Dawesi March 2, 2014 at 8:18 am #

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

  47. Peter March 2, 2014 at 7:47 pm #

    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 ?

    Thanks

  48. Sani Elfishawy March 3, 2014 at 12:42 pm #

    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?

  49. LA March 5, 2014 at 10:29 am #

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

  50. Alberto Lopez March 6, 2014 at 12:08 am #

    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?

    regards
    Alberto Lopez

  51. Sam March 16, 2014 at 7:41 pm #

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

  52. Malek March 20, 2014 at 5:46 pm #

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

    • codexmonkey April 30, 2014 at 4:07 pm #

      [root]/www/js/index.js

  53. Jay T. March 20, 2014 at 10:35 pm #

    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 May 29, 2014 at 7:40 am #

      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 May 30, 2014 at 7:27 am #

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

  54. Jay T. March 21, 2014 at 12:16 pm #

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

    xmlns:gap=”http://phonegap.com/ns/1.0″>

    plus added to config file….

  55. linda March 21, 2014 at 1:12 pm #

    Hi!

    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?

  56. Mark March 25, 2014 at 12:25 am #

    Awesome tutorial!

  57. Alejandro March 25, 2014 at 7:43 am #

    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 windows.open on the first steep of the route() function, it works. If I change hash and execute again the window.open it doesn’t do anything. It also happends with the console.log, etc…

    any help?

  58. Carlos Garcia March 26, 2014 at 11:24 am #

    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?

  59. ttemp March 29, 2014 at 8:34 pm #

    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 https://github.com/apache/cordova-plugin-contacts/blob/431eeea9f5d7ea738b3b8277162a4ab4313dc32f/doc/index.md and so does geolocation at least for galaxy s2)

    thanks this is really great

  60. Rada April 3, 2014 at 3:25 pm #

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

  61. Chris April 8, 2014 at 5:27 am #

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

  62. vitamix blender April 8, 2014 at 10:05 pm #

    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.

  63. Steve James April 9, 2014 at 5:16 am #

    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.

    Thanks,
    Steve

    • Steve James April 10, 2014 at 9:08 am #

      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.

  64. David Chen April 11, 2014 at 8:32 pm #

    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:

    chrome://inspect

  65. Safaa Alnablsi April 16, 2014 at 2:38 am #

    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

  66. www.bestdentistqueens.biz April 16, 2014 at 10:45 pm #

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

  67. Sumit April 21, 2014 at 6:47 am #

    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.

  68. AndyG April 21, 2014 at 10:11 am #

    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…

    :-)

  69. Dariush April 22, 2014 at 2:53 am #

    Hi.. i want just say thanks…
    :)

  70. Dwain Talburt April 23, 2014 at 11:12 pm #

    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…

  71. Rendy April 24, 2014 at 4:52 am #

    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?

  72. User123 April 25, 2014 at 1:51 am #

    Thank you very much for the tutorial!

  73. Harry April 27, 2014 at 3:03 pm #

    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.

    • Rowan June 24, 2014 at 8:13 pm #

      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?

  74. Ottawa Senators Black discount hockey coupon code

  75. Bankruptcy Attorney Phoenix Az April 28, 2014 at 11:12 pm #

    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!

  76. Shashikant Kumar April 30, 2014 at 6:07 am #

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

  77. Tad May 1, 2014 at 11:20 am #

    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.

  78. Greg May 2, 2014 at 5:50 am #

    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.

  79. crazy shirts Coupon May 6, 2014 at 5:56 am #

    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.

  80. sir May 6, 2014 at 10:56 am #

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

    • Phu May 16, 2014 at 9:17 am #

      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

  81. Leona May 6, 2014 at 9:21 pm #

    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.

  82. sigmoideoskopi May 7, 2014 at 8:06 am #

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

  83. prinsgatan 12 göteborg May 7, 2014 at 8:09 am #

    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.

  84. jignesh May 8, 2014 at 5:57 am #

    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.

  85. No contract May 9, 2014 at 3:02 am #

    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.

  86. Neida Monnot May 10, 2014 at 2:30 pm #

    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.

  87. DeveloperJoe May 12, 2014 at 10:42 pm #

    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?

  88. wart free home remedies acid reflux May 14, 2014 at 1:59 pm #

    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.

  89. wirystomach4373.skyrock.com May 14, 2014 at 8:16 pm #

    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.

  90. 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.

  91. Swapna May 19, 2014 at 11:02 am #

    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 ?

    Thanks
    Swapna

  92. Paul Schreuder May 21, 2014 at 4:32 am #

    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.

    Cheers
    Paul

  93. Trevor Best May 22, 2014 at 5:19 am #

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

  94. bodymindspiritintegration.com May 22, 2014 at 8:25 pm #

    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

  95. gloriousshopper07.blog.fc2.com May 23, 2014 at 8:47 am #

    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.

  96. Felipe May 23, 2014 at 9:36 am #

    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?

  97. Lomas Joshi May 28, 2014 at 1:08 am #

    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.

  98. designer May 30, 2014 at 5:14 pm #

    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?

  99. Leon Mccurry June 4, 2014 at 9:56 pm #

    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.

  100. turbulencetrainingreviewed.tumblr.com June 5, 2014 at 5:11 pm #

    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
    you.

  101. Breann Holsonback June 6, 2014 at 4:29 pm #

    Great

  102. szkoła alternatywna w zielonej gorze June 10, 2014 at 8:54 am #

    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.

  103. Click Here June 14, 2014 at 6:33 pm #

    Greetings from Carolina! I

  104. online free hack June 15, 2014 at 3:20 am #

    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.

  105. jerrodisaacson.pen.io June 15, 2014 at 8:26 pm #

    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.

  106. Wilda June 16, 2014 at 2:39 pm #

    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.

  107. Http://Izaler53.Centerblog.Net/1- June 21, 2014 at 7:14 pm #

    * 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.

  108. hungryguy June 24, 2014 at 4:40 am #

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

  109. Max June 24, 2014 at 5:34 am #

    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
    ordova\node_modules\cordova-lib\src\cordova\superspawn.js:131:23)
    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 June 24, 2014 at 5:35 am #

      Can you help me plz ? Thank you .

  110. hungryguy June 24, 2014 at 6:10 am #

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

  111. Carmine Allmond June 25, 2014 at 1:51 pm #

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

  112. ready app June 26, 2014 at 6:24 am #

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

  113. china baidu June 28, 2014 at 12:09 am #

    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 ;)

  114. dragon city cheat tools online June 28, 2014 at 9:24 pm #

    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.

  115. barcodescanner June 30, 2014 at 3:56 am #

    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.

  116. Tod July 1, 2014 at 11:25 pm #

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

  117. Rosalie July 7, 2014 at 4:12 am #

    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!

  118. Antonio July 7, 2014 at 7:15 am #

    Hi, great tutorial.
    One question:

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

  119. Ghayth Mkhinini July 9, 2014 at 7:28 am #

    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 ?

  120. nose trimmer July 11, 2014 at 6:24 pm #

    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.

  121. cul femme légère July 12, 2014 at 8:03 am #

    Post incroyablement cultivant

  122. 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.

  123. Kurtis July 15, 2014 at 11:23 am #

    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.

  124. home designer software July 17, 2014 at 5:58 am #

    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.

  125. Tamela July 28, 2014 at 7:33 pm #

    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.

  126. Fjito August 13, 2014 at 11:12 am #

    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?

  127. Muhammad Nasir Khan August 21, 2014 at 6:19 am #

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

  128. Vishal September 14, 2014 at 2:02 pm #

    If you are wondering on Part 4 (as i was), there’s a new tutorial http://ccoenraets.github.io/cordova-tutorial/ which follows new file structure in tutorial.

  129. Vishal September 14, 2014 at 2:03 pm #

    If you are wondering on Part 4 (as i was), there’s a new tutorial http://ccoenraets.github.io/cordova-tutorial/ which follows new file structure(in github repository) in tutorial.

  130. Ahmed September 18, 2014 at 4:02 am #

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

  131. dheeraj October 7, 2014 at 3:40 am #

    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.

Trackbacks/Pingbacks

  1. New Cordova/PhoneGap 3.x Tutorial | Christophe Coenraets - January 8, 2014

    [...] Cordova/PhoneGap 3.x Tutorial [...]

  2. PhoneGap 3.x Tutorial - January 17, 2014

    […] The tutorial can you find here. […]

  3. PhoneGap for Hybrid App Development | Robin C Samuel - January 30, 2014

    […] I’m would suggest Mr.Coenraets tutorial for phonegap beginner, as there is a well explained tutorial in his blog. http://coenraets.org/blog/cordova-phonegap-3-tutorial/ […]

  4. Making An App (Industry Student Project) Day 03 | T Ratnayake - April 28, 2014

    […] been using this tutorial, and I’ve recommended that my whole team do it for the weekend as baseline knowledge as it’s a […]

  5. Building a Native Mobile App with Phonegap and jQuery Mobile 1.4 | Gajotres.net - May 23, 2014

    […] versions of Cordova changed this a lot. If you are using Cordova 3.1 and above you should read this article to find out how to make android project from Cordova CLI.   Open Eclipse again and press […]

  6. Tutorial sobre phonegap-cordova - formandomeformandome - May 29, 2014

    […] Tutorial para crear una aplicación en PhoneGap en el que está basado este documento. […]

  7. APP#1: Stream music tracks from soundcloud using Cordova (Phonegap 3.x) | MythLab - June 15, 2014

    […] some basic knowing about html,css and javascript. 2. Should be familiar with cordova/phonegap.( This one helped me […]

  8. Cordova (aka PhoneGap) 3.x Tutorial | Christophe Coenraets | - July 15, 2014

    […] Curated from coenraets.org […]

  9. Zur ersten eigenen Android App - Stefan Wilhelm Info - July 31, 2014

    […] bzw. viel widersprüchliches. Ich empfehle dazu also das Tutorial von Christophe Coenraets unter dieser Adresse. Allerdings auch nur bis zu einem bestimmten […]

  10. Fix Homeview.js Errors - Windows XP, Vista, 7 & 8 - September 19, 2014

    […] Cordova (aka PhoneGap) 3.x Tutorial | Christophe Coenraets – Part 1: Creating a Cordova Project. Make sure an up-to-date version of Node.js is installed on your system. Open Terminal (Mac) or a Command window (Windows), and …… […]

Leave a Reply

css.php