Part 2b - AppForum Dev Lab - Save Scan Data
Before we get into saving the scan data, let's first load the breakout session data into a drop down so the user can select the presentation that they will be scanning attendees for.
Let's open up the index.html file and replace our placeholder inside the selector div section with a
As you can see we created a disabled option as a placeholder and indicated that it should call a javascript function sessionChange(). Before we create the create the sessionChange function let's create a function,loadSessionSelect() to load more options on page load:
function sessionChange()
{
}
function loadSessionSelect()
{
//load session Select with data
var sessionList=document.getElementById("session");
for (i=0;i
{
eventSession = eventData[i]
var option=document.createElement("option");
option.text=eventSession.title;
option.value=i; // Put index here not sessionID so we don;t have to do DB call to get session info
sessionList.add(option);
}
}
Copy the data.js file from the USB stick and make sure it is referenced in the head section of the index.html
This file contains some basic information for each of the breakout presentations stored in a JSON object. We are using the javascipt variable eventData that is inside the data.js file. This allows us to easily reuse the application for different conferences and just modify one text file containing the presentation info.
Now modify the onPageLoad function to call loadSessionSelect() so that the session select drop down shows the Titles of all of the sessions.
Let's test loading the index.html file now, but instead of loading it on the device - let's load it inside of Google Chrome browser. Yup, you heard me right, Google's Chrome Browser. Chrome, Safari and other browsers that are based on webkit will respond very similar to pages loaded inside of RhoElements. Drag your file over to Chrome to load the index.html.
What happened you say? Well let's turn on Chrome's very useful develoepr tools by pressing CTRL-SHIFT-I (Or Tools/Developer Tools from the menu). You should see a javascript error indicated in the lower right hand corner. Click on it and you will see it indicating that generic is not defined. This is because on your desktop, the RhoElements plugin is not recognized by Chrome. "generic", if you recall if what we used in the database file for writing out to the log file when an error happened during the database transaction.
But that does not mean that you can't use your desktop browser to help you develop a RhoElements application. In fact Chrome is very useful for this task. I will do a deep dive on this topic at a later time, but for now let us put in some simple code to detect if we are running inside RhoElements.
Let us add a variable to the top of our javascript called isRhoElements and set it to false.Now let's add the following snippet to the beginning of the onPageLoad function that will check to see if we are using RhoElements:
RhoElements will include a string MotorolaWebKit inside of the User Agent string. So we can use this as a mechanism to check to see if the app is running inside of RhoElements. Now that we will have a variable accessible from any of our javascript, let's go back into the db.js file and modify the onError function:
Refresh Chrome browser and you will no longer see any Javascript errors.
If you click on the Resources tab inside Chrome Browser's Developer Tools you will also Databases listed. If you click through you will see that the database EventTracker has been created with sessionAttendees table:
So where does Google Store these databases. Well it is saved in a similar structure to what RhoElements is doing.
Google Chrome is storing all Web SQL databases in:
Windows Vista or 7: \Users\_username_\AppData\Local\Google\Chrome\User Data\Default\databases
Windows XP: \Documents and Settings\_username_\Local Settings\Application Data\Google\Chrome\User Data\Default\databases
Mac OS X: ~/Library/Application Support/Google/Chrome/Default/databases
Linux: ~/.config/google-chrome/Default/databases
Except there is no .DB extension. If you added a .db you would be able to open it in the SQLite client we used before.
Ok so we are almost there. Before we create the code to insert scan data into the sessionAttendees table, we need to create that sessionChange() function that the drop-down will call after the user changes the selected presentation that they will be scanning attendees for. For this I am going to introduce another HTML5 concept called session storage. Session storage is like an enhanced type of 'cookie'. It let's you create name/value pairs and have your application in control of them and not the browser. We will be using the localStorage object with methods .setItem(name,value) and .getItem(name).
In the onPageLoad function lets create a localStorage item called sID -this will contain the actual sessionID that is selected:
Now let's create the sessionChange() and put in a similar statement so that the selected value is stored in the sID localstorage variable.We will also add some code to enable the scanner now that as session has been selected and also some code to display the Event Session Data into the sessionDetail DIV. By the way, these localStorage variables, like the WebSQL is persistant across sessions as well as device reboots, etc.
function sessionChange()
{
sessionIndex = document.getElementById('session').value;
//remember what
localStorage.setItem('sID',eventData[sessionIndex].sessionId);
//Display Session Detail
var sDetail = document.getElementById('sessionInfo');
sDetail.innerHTML = eventData[sessionIndex].title + '
' + eventData[sessionIndex].speaker + '
' + eventData[sessionIndex].room + ' ' + eventData[sessionIndex].displayTime;//Enable the scanner
if(isRhoElements)
{
//enable scanner since a session was selected - ok if already enabled
enableScanner();
}
}
Now let's save everything and refresh the index.html inside of Chrome Browser. Choose an option from the drop down and you will not only see the details displayed inside the sessionDetail DIV, but if you still have the Chrome Developer tools open, you will see the Local Storage variable sID change every time you select a new option (don't forgot to click the refresh icon in the developer tools to see the current value):
Now lets go back to the DIV placeholders and add one more to keep track of the number of people scanned for each session.
Let's modify the doScan() and call a function dbInsertScanData() to insert the record and update the display to show a new attendee count.
function dbInsertScanData( scanData)
{
sessionId = localStorage.getItem('sID');
db.transaction(
function(tx)
{
tx.executeSql("INSERT INTO sessionAttendees ( sessionId,scanData) VALUES (?,?)", [ sessionId, scanData],
function(tx, result)
{
//Clear Last Scanned
var attendeeCount = document.getElementById('attendeeCount');
attendeeCount.innerHTML = parseInt(attendeeCount.innerHTML) + 1;
},
onError
);
}
);
}
Before I test this with an actual device, I will create a simple test function and hook it to a temporary button's onClick event so I can check to make sure this is working.
function testScan()
{
var $vcardSample = 'BEGIN:VCARD\nVERSION:2.1\nN:Galvin;Robert\nFN:Rob Galvin\nORG:Motorola Solutions Inc\nEMAIL:rob.galvin@motorolasolutions.com\nEND:VCARD\n';
dbInsertScanData($vcardSample);
}
One last thing - lets change it do that it shows the total scanned in attendees each time a session is selected. Inside of db.js lets create one new function: dbLoadData
function dbLoadData(sessionId)
{
db.transaction(function(tx) {
tx.executeSql("SELECT Count(*) as numAttendees FROM sessionAttendees where sessionId = ?", [sessionId],
function(tx, result) {
item = result.rows.item(0);
var attendeeCount = document.getElementById('attendeeCount');
attendeeCount.innerHTML = item['numAttendees'];;
},onError);
});
}
And then in the sessionChange function add this line of code:
dbLoadData(eventData[sessionIndex].sessionId);
Now lets refresh the app in Chrome Browser. Select a session and click the Test Button, Then Change the session and click the test button again. Open the developer tools and view the database resources again. You should now see that the records are properly getting into the tables and each 'test scan' is linked to a selected session. You should also see that it loads the counted records from the selected session each time a new option is selected.
Now we have the application working quite well by now. Let's move it to the device and test it from there with the actual scanner.Notice that the scanner is not enabled when the page loads, but only after a session has been selected from the list.
If we copy the file to the PC and view it in the SQLite client you will be able to see that the application is working on the device.
Let's add a button that will allow the user to exit the application.
And now, lets copy the app.css and graphic PNG files from the USB drive and change the HEAD and BODY sections of the index.html to look like:
Event Attendee Tracker
0
Robert Galvin