In this post, we'll see how to build upon our jQuery Mobile and
Have you ever ate at a restaurant and been asked to complete a survey? Normally the experience involves calling some 1-800 number and interacting with a robotic voice. Not fun.
In this
We'll start by discussing the widgets jQuery Mobile provides to build mobile friendly forms quickly, then
Next, we'll figure out where to send the form data. Normally this involves a complex back end with a database backed API - a bit much for this example. Luckily,
Let's get started.
We'll start by getting the actual survey UI created. jQuery Mobile provides the following eight widgets for building forms:
jQuery Mobile widgets can be created declaratively by adding data-role
attributes to HTML elements. However, most form widget will auto-enhance without any configuration at all. For example consider the <select>
<select>
<option>One</option>
<option>Two</option>
<option>Three</option>
</select>
When included in jQuery Mobile, this will display as follows:
You can see that jQuery Mobile automatically enhanced the element into a bigger mobile-friendly version of <select>
data-role="none"
attribute to the element. This
<select data-role="none">
<option>One</option>
<option>Two</option>
<option>Three</option>
</select>
In our
Now that we've seen the widgets available, let's use them to build our survey. We'll be asking users three questions:
Here's the form we will present to the user to complete these questions.
<p><strong>Please complete the following survey.</strong></p>
<form>
<div>
<!-- Create a controlgroup widget -->
<fieldset data-role="controlgroup" data-type="horizontal">
<legend>Which location did you visit?</legend>
<input type="radio" name="location" id="location-north" value="north" checked>
<label for="location-north">North</label>
<input type="radio" name="location" id="location-south" value="south">
<label for="location-south">South</label>
<input type="radio" name="location" id="location-west" value="west">
<label for="location-west">West</label>
</fieldset>
</div>
<div>
<!-- Create a switch widget -->
<!-- Switches are consider a type of slider by the framework therefore -->
<!-- data-role="slider" is used. The framework knows to convert -->
<!-- select elements with data-role="slider" into switches. -->
<label for="appetizer">Did you order an appetizer?</label>
<select name="appetizer" id="appetizer" data-role="slider">
<option value="no">No</option>
<option value="yes">Yes</option>
</select>
</div>
<div>
<!-- Create a slider widget -->
<label for="rating">Please rate your overall experience from 1 to 5:</label>
<input type="range" name="rating" id="rating" value="3"
min="1" max="5" step="1" data-highlight="true">
</div>
<div>
<button>Submit</button>
</div>
</form>
This displays as follows in Icenium's iOS simulator:
Note: In order for the switch and slider widgets to work with a mouse in Icenium's simulators you need to turn on touch event emulation in Chrome.
As you can see, jQuery Mobile makes it easy to build
But, now what? We have a form but where do we send the data?
Web developers are comfortable with
Let's see how we can tie our form into Everlive.
For our hybrid app, the first step to using Everlive is to download the JavaScript SDK and import it into our project. You can download the JavaScript SDK at http://docs.telerik.com/platform/backend-services/development/javascript-sdk/introduction. This is shown below.
As you can see Everlive has SDKs for multiple other platforms. Therefore it's possible to store and retrieve the same data from completely different technologies - for now though, we'll be concentrating the on the JavaScript SDK.
To use the SDK we have to import it into our
From the dialog that pops up you can select files from your file system, or just drag and drop the file into the dialog. We'll be using everlive.all.min.js.
You can also drag and drop files within Icenium's project navigator to organize your project. Let's drag everlive.all.min.js into the scripts folder. Then we can import the JavaScript SDK with the following script tag.
<script src="scripts/everlive.all.min.js"></script>
Now that we have the JavaScript SDK imported, we need one more line of code to initialize the SDK. Create a new main.js in your project's scripts folder and add the following:
new Everlive({ apiKey: '#YOUR-KEY-HERE' });
You can get your API key by viewing your project on http://everlive.com.
Our last step is configuring the back end. Everlive backends are made up of content types, which are like to
These content types give you an excellent starting point for implementing common tasks such as user management and file storage. For our purposes however, we'll want to create a new content type from scratch. Click the "Create a Content Type" button and configure a new Ratings content type with the fields shown below.
This gives our content type three new fields - location, appetizer, and rating - that map to the fields on our survey. And with that, our back end setup is complete! No complex database to setup or maintain.
Now that we have a back end the next step is to connect it to our front end. We'll see how this is easily accomplished with a few lines of JavaScript.
Everlive's JavaScript SDK that we included has APIs for performing CRUD (Create Read Update Delete) operations on our application's content types.
To tie our survey to our back end, we have to listen for the survey's form submission, grab the data we need, and send it to Everlive. The code below does this; place it in your app's scripts/main.js file.
// Add an event listener for the survey form's submission.
$('form').on('submit', function(event) {
// Prevent the default form submission as we'll be sending the data to Everlive.
event.preventDefault();
// Retrieve the data from the form.
var data = {
location: $(this.location).filter(':checked').val(),
appetizer: $(this.appetizer).val() == "yes",
rating: $(this.rating).val()
};
// Use jQuery Mobile to show a loading indicator while we send data
// to our Everlive backend.
$.mobile.loading('show', { text: 'Processing...', textVisible: true });
// Create a new rating with our project's "Ratings" content type using
// the SDK's create method.
Everlive.$.data('Ratings').create(data,
// Function to run on a successful transfer.
function(data){
// Hide the loading indicator now that processing is complete.
$.mobile.loading('hide');
// Take the user to another page to tell them the submission worked.
$.mobile.changePage('#success');
},
// Function to run on erred transfers.
function(error){
// Let the user know if something went wrong.
alert('Sorry, an error occurred processing your survey. Please try again later.');
}
);
return false;
});
On successful submission, this script uses jQuery Mobile's changePage()
method to send the user to a success page. We'll use the following success page for now. Add this to the project's index.html.
<div data-role="page" id="success">
<div data-role="header">
<h1>Thanks!</h1>
</div>
<div data-role="content">
<p>Your survey was successfully processed. Thank you.</p>
<a href="#results" data-role="button">View Results</a>
</div>
</div>
Now when the user submits our survey they will see the following.
And in Everlive, if we look at our rating content type we have the following entry:
That's all there is to it. As users fill out our survey our back end will be populated with the data automatically.
But what good is a ton of raw data? The good news is Everlive makes it just as easy to get data out as it was to put in it.
As we discussed, Everlive's JavaScript SDK has APIs for all CRUD operations. To get data out of Everlive, we can use the getById()
method to get an individual rating, or the get()
method to get all of them. For our survey, we want to aggregate all data, therefore we'll use get()
. The following invokes get()
to retrieve all Ratings.
Everlive.$.data('Ratings').get();
This does an AJAX request to retrieve the data and returns a promise object that is resolved when the data has returned. In simple terms, this means you can attach functions to run when the data is successfully retrieved, and when something goes wrong. This is shown below.
Everlive.$.data('Ratings').get()
.then(
// Success callback
function(data) {
alert(JSON.stringify(data));
},
// Error callback
function(error) {
alert(JSON.stringify(error));
}
);
After users fill out a survey they like to see the aggregated results of the form they just filled out. Now that we have a means of retrieving the data, let's add a means of displaying it in our UI.
First we'll add a link from our success page to a new results page.
<div data-role="page" id="success">
<div data-role="header">
<h1>Thanks!</h1>
</div>
<div data-role="content">
<p>Your survey was successfully processed. Thank you.</p>
<!-- Link to results page -->
<a href="#results" data-role="button">View Results</a>
</div>
</div>
Next, when the user clicks the link to the results page, we need to load the results and show them to the user. How will we know when the user visits the results page? jQuery Mobile fires a number of events as the user interacts with pages in the application. For our purposes, we'll use the pageshow
event.
First, here's a starting point for the new results page:
<div data-role="page" id="results">
<div data-role="header">
<h1>Results</h1>
</div>
<div data-role="content">
<!-- We'll add some tables for the results themselves here -->
</div>
</div>
Then in JavaScript will listen for pageshow
event on this new page and load our data.
// Subscribe to the pageshow event on the results page.
$('#results').on('pageshow', function() {
// Show a loading message while the retrieve call occurs.
$.mobile.loading('show', { text: 'Loading results...', textVisible: true });
// Retrieve the ratings data from Everlive.
Everlive.$.data('Ratings').get()
.then(
// When the data loads call a function to display the data.
// We'll look at what this function does momentarily.
displayResults,
// Let the user know if something went wrong.
function(error) {
alert('Sorry, loading the survey results failed.');
}
);
});
This gets us the data, but we still have to show it to the user. For simplicity, we'll build a few minimal tables on the results page. Place the following in the content of the results page.
<table class="ui-table">
<thead>
<tr>
<th colspan="2">Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>North</td>
<td id="results-north"></td>
</tr>
<tr>
<td>South</td>
<td id="results-south"></td>
</tr>
<tr>
<td>West</td>
<td id="results-west"></td>
</tr>
</tbody>
</table>
<table class="ui-table">
<thead>
<tr>
<th colspan="2">Appetizer</th>
</tr>
</thead>
<tbody>
<tr>
<td>Yes</td>
<td id="results-yes"></td>
</tr>
<tr>
<td>No</td>
<td id="results-no"></td>
</tr>
</tbody>
</table>
<table class="ui-table">
<thead>
<tr>
<th colspan="2">Overall Rating</th>
</tr>
</thead>
<tbody>
<tr>
<td>One</td>
<td id="results-1"></td>
</tr>
<tr>
<td>Two</td>
<td id="results-2"></td>
</tr>
<tr>
<td>Three</td>
<td id="results-3"></td>
</tr>
<tr>
<td>Four</td>
<td id="results-4"></td>
</tr>
<tr>
<td>Five</td>
<td id="results-5"></td>
</tr>
</tbody>
</table>
Then, we'll use the following function to aggregate the data and populate the tables:
function displayResults(data) {
// Create a counter for each result. Start all counters at 0.
var results = {
location: { north: 0, south: 0, west: 0 },
appetizer: { yes: 0, no: 0 },
rating: { '1': 0, '2': 0, '3': 0, '4': 0, '5': 0 }
};
// Loop over each individual result, increment the appropriate counters.
data.result.forEach(function(result) {
results.location[result.location]++;
results.appetizer[(result.appetizer ? 'yes' : 'no')]++;
results.rating[result.rating]++;
});
// Fill the table cells with the data as appropriate.
$('#results-north').text(results.location.north);
$('#results-south').text(results.location.south);
$('#results-west').text(results.location.west);
$('#results-yes').text(results.appetizer.yes);
$('#results-no').text(results.appetizer.no);
$('#results-1').text(results.rating['1']);
$('#results-2').text(results.rating['2']);
$('#results-3').text(results.rating['3']);
$('#results-4').text(results.rating['4']);
$('#results-5').text(results.rating['5']);
// Hide the loading indicator now that the data is visible.
$.mobile.loading('hide');
};
Now when the user clicks view results they will see the following:
That's all it took to retrieve all data and get it on the screen. Admittedly, the display is very basic, but it gets the job done for a demonstration. If you're looking for rich ways to display your data such as bar graphs and pie charts, check out Kendo UI's data visualization libraries.
In this article we saw how to build a form using jQuery Mobile and connect it to an Everlive backend. The user is now able to complete a survey and see aggregated results automatically.
The full source of our sample application is in this GitHub repository. Feel free to poke around in the source, or fork the repo and make it your own.
Looking to learn more? The following resources can help you explore all that jQuery Mobile and Everlive have to offer.
TJ VanToll is a frontend developer, author, and a former principal developer advocate for Progress.