Building the Resource Details Screen

Building the Resource Details Screen

Before we implement functionality for gathering the resources, though, there are a few things that we need to do in the main moundz.js file that will assist us with managing the state of the application. Until now, we have simply been displaying some debug-level information when a marker has been selected, and that really is no longer appropriate for what we need to do. The following code shows the modifications required to the moundz.js file to assist with keeping track of resource data in the application.

MOUNDZ = (function() { // initialize constants var DEFAULT_ZOOM = 8,

CHAPTER 12: Polishing and Packaging an App for Release

GEOMINER_MOUNDZ_URL = 'http://api.geominer.net/v1/moundz';

// initialize variables var geominer = null,

markerData = {}, currentResource = '',

posWatchId = 0;

/* private functions */

function activateMarker(marker) { // iterate through the markers and set to the inactive image for (var ii = 0; ii < markers.length; ii++) {

markers[ii].setIcon('img/pin-inactive.png'); } // for

// update the specified marker's icon to the active image marker.setIcon('img/pin-active.png');

// update the navbar title using jQuery $('#marker-nav a[href="#marker-detail"]')

.find('.ui-btn-text') .html(marker.getTitle());

// update the active marker title currentResource = marker.getTitle();

// update the marker navigation controls updateMarkerNav(getMarkerIndex(marker));

} // activateMarker

function markResources(resourceType, deposits) {

for (var ii = 0; ii < deposits.length; ii++) {

// add the marker for the resource deposit

addMarker(

new google.maps.LatLng(deposits[ii].lat, deposits[ii].lng), deposits[ii].name, deposits[ii]);

} // for } // markResources

/* exported functions */

function addMarker(position, title, data) {

// create a new marker and display it on the map var marker = new google.maps.Marker({

position: position, map: map, title: title, icon: 'img/pin-inactive.png'

markerPosition = position;

CHAPTER 12: Polishing and Packaging an App for Release

// save the marker data markerData[title] = data;

// add the marker to the array of markers markers.push(marker);

// capture touch click events for the created marker google.maps.event.addListener(marker, 'click', function() {

// activate the clicked marker activateMarker(marker);

}); } // addMarker

var module = { ... };

return module; })();

These changes to the code have been put in place to facilitate storing the data received from the Geominer API. While storing some arbitrary content was useful back when we were putting together our boilerplate mapping application, we have outgrown it here.

The changes to the addMarker and markResources functions are simple inline changes, in which we change references of content to data (e.g., markerContent becomes markerData).

The changes to the activateMarker function do a little more. Previously, the activateMarker function set the active marker (and the inactive markers) to have the correct icon, updated the marker title in the nav button, and also updated the marker detail content and attached relevant events. Now that we are working with data instead of the marker content, it makes sense for us to handle things slightly differently. The code for updating the #marker-detail div content and binding and unbinding to the events of the appropriate links has been removed, and has been replaced with a simple call to set the currentResource variable to the title of the selected marker.

With the currentResource variable in place, we can move on to updating the details for that resource in the #marker-detail display. Let’s begin by making some changes to our index.html file:

<div id="marker-detail" class="noauth" data-role="page"> <div data-role="header"> <h1>Resource Details</h1> </div> <div data-role='content'>

<h2></h2> <div id="resavail"></div> <div data-role="fieldcontain">

<label for="slider">Amount to Gather:</label> <input type="range" name="slider" id="slider" value="1" min="1" max="5" />

</div> <a id="btnGather" href="#" data-role="button">Gather</a>

CHAPTER 12: Polishing and Packaging an App for Release

</div> </div>

Here we see some more jQuery Mobile code coming into play. For instance, notice the div marked with the data-role="fieldcontain" attribute. This tells jQuery Mobile that we are dropping in a section of form controls. Additionally, note the use of the new

HTML5 range input type (www.w3.org/TR/html-markup/input.range.html), which jQuery Mobile replaces with its own interpretation of the range control by way of an attractive graphical slider. With this HTML in place, our Resource Details screen will look similar to Figure 12–6.

Figure 12–6. jQuery Mobile does a very nice job of providing a simple, clean mobile UI. OK, it’s time to actually show some useful information on this screen. We will do this by

detecting the user navigating to the Resource Details screen by capturing tap events on relevant links. The following modifications to moundz.js demonstrate how we do this:

MOUNDZ = (function() { ...

// initialize variables var geominer = null,

supportsTouch = 'ontouchstart' in window;

/* private functions */

function updateResourceDetails() { var currentData = markerData[currentResource];

CHAPTER 12: Polishing and Packaging an App for Release

if (currentData) {

$('#marker-detail h2').html(currentData.name); } // if } // updateResourceDetails

/* exported functions */

function initScreen() { // size the canvas to the height of the page minus the header $('#map_canvas').height(

$('#main').height() - $('#main div[data-role="header"]').outerHeight() - $('#main div[data-role="footer"]').outerHeight() - 30

// bind to the marker detail tap event $('a[href="#marker-detail"]').live(supportsTouch ? 'tap' : 'click',

updateResourceDetails);

} // initScreen

... var module = {

return module; })();

This code performs a couple of functions:

1. It defines a new function, updateResourceDetails, which uses the

currentResource variable that we defined earlier to retrieve the data on the resource. This data is then used to update the app display; in this case, we are simply updating the header within the display, but we will add more functionality very soon.

Download from Wow! eBook <www.wowebook.com>

2. The initScreen function is modified to attach an event handler to any links that direct the user to the #marker-detail screen. This is done using the jQuery live function ( http://api.jquery.com/live), which means that the event handler is put in place for any elements (including ones that might be dynamically created later) matching the selector.

Also worth noting in this code is the use of the ternary (or elvis) operator with the supportsTouch variable. This, combined with the initialization of the supportsTouch variable at the start of the module, provides us with a useful mechanism that will allow us to test our application both on mobile and desktop browsers. It does this by appropriately attaching to either the tap or the click event handler, depending on whether the current device supports touch interaction.

CHAPTER 12: Polishing and Packaging an App for Release

This is very useful during the development of mobile web applications, as debugging with a desktop browser is generally a more pleasant experience than working with the Android debugging console—see Appendix A for more information on the topic.

With the code in place, tapping the Resource Details button in the navigation bar will show us a Resource Details screen similar to that shown in Figure 12–7.

Figure 12–7. Our Resource Details screen is now dynamically updated. Now that we have the groundwork in place to update the display of the Resource Details

screen, it’s time to make it pretty—we are definitely overdue for some more CSS3 gradients.

The following CSS (added to the end of moundz.css) gets us partway there: /* resource details screen styles */

#marker-detail h2 { text-align: center; margin: 0 0 10px; color: #777;

#resavail { background: #333 -webkit-gradient(linear, left top, right top, from(#099), to(#0A0)) no-repeat; border: 2px #333 solid; -webkit-border-radius: 8px; -webkit-box-shadow: #555 0 1px 2px; height: 20px; font: bold 0.9em Arial; letter-spacing: 3px;

CHAPTER 12: Polishing and Packaging an App for Release

text-align: center; color: white; padding: 5px 0 2px; text-shadow: none;

} With the CSS applied, the Resource Details screen should appear similar to Figure 12–8.

Figure 12–8. Our Resource Details screen is starting to look good, but what is that under the resource name? While the CSS makes things look a little prettier, that bar beneath the resource name is

a bit of a mystery. What is it for? Well, we are going to turn that into a bar that displays the current resource availability for the resource by adding some additional code to the updateResourceDetails function that we recently created.

function updateResourceDetails() { var currentData = markerData[currentResource]; if (currentData) {

var percAvail = 0;

// determine the resource available percentage

if (currentData.total !== 0) { percAvail = Math.round((currentData.avail / currentData.total) * 100); } // if

$('#marker-detail h2').html(currentData.name); $('#resavail')

.html(currentData.avail + ' / ' + currentData.total)

.css('-webkit-background-size', percAvail + '% 100%');

} // if } // updateResourceDetails

CHAPTER 12: Polishing and Packaging an App for Release

In the preceding code you should be able to see where we are tapping into some of the extra data that is returned from the Geominer API. With that data we do two things:

1. Calculate the percentage of resources available using some trivial math. That percentage value is then used to dynamically apply a -webkit-background-size style to the #resavail div. Our particular definition for the style instructs the div to size the background image (note that gradients are treated as images) to a calculated percentage of the width and 100 percent of the height. Essentially, we have created a simple progress bar with very little code at all.

2. Update the content of the #resavail div to display a textual description of the quantity of resource available at the particular location.

After implementing this JavaScript code, our Resource Details screen will be similar to Figure 12–9.

Figure 12–9. The Resource Details screen showing that this location already has many resources gathered This brings us to the point where our Resource Details screen is showing us some

sensible, reasonably well-presented information. It’s now time to look at gathering some resources.