Creating a Data Abstract client widget - Part 4

This is the 4th article in a 4 part series (the last for now)

  1. Using DashCode to create an interactive widget
  2. Creating an interactive widget without Dashcode
  3. Creating a RemObjects SDK client widget
  4. Creating a Data Abstract client widget (this article)

In this article we will look at Data Abstract client widgets created without using Dashcode.

Data Abstract PCTrade Workers Image Gallery Widget

For this demo we connect to the PCTrade sample database and display worker images. This creates an image gallery type widget, except the images are pulled live from a remote database on each activation. You can see an example of what this demo will look like on our website. That demo may be updated in the future, but our widget will by default pull from the same database.

Data Abstract JavaScript Library Files

The following parts are needed for any Data Abstract JavaScript client you want to write. The minified versions are available on our sample server, or they ship in the .NET or Delphi versions of Data Abstract (coming soon to the Xcode version).

These files need to be included in our widget package.

Assembling the Widget Package

As you recall, the minimum requirements for a widget are:

  • main.html – The main html file.
  • Default.png – The “preview” image that is visible before the widget activates. Also determines widget size and aspect ratio.
  • Info.plist – The manifest that describes the widget.

You can create the parts from scratch, or download this package of all the files. We’ll take a closer look at how it all comes together. The core of the functionality is in the main.js. While you could put all that JavaScript in the main.html file, putting it in a separate file makes for better maintainability.

I usually create my default.png files by taking a screen shot of my HTML page running in a browser window. Somethings I’ll edit it after taking the screen shot. Generally you want to have the screen shot be of the first screen the user sees so the transition from image to active widget is smooth.

All these files need to be in the same folder, and the folder needs to be renamed with a .wdgt extension. Remember: If you double-click that folder, it will be deleted and installed in your Dashboard. Use the context menu to show package contents instead.

Inside the main.html File

At the top of the main.html file, in the `` block, we reference all our scripts. It is important that these scripts are local and included in the package. They will not work from iBooks if they are remote.

>http-equiv="Content-Type"content="text/html; charset=UTF-8"/>     >
The `` is also really simple.
onload="loadData();">   id="wrapper">   >Data Abstract for JavaScript>>PCTrade workers gallery widget>id="content">href="javascript:void(0)"onclick="showPrevious();">prev> / href="javascript:void(0)"onclick="showNext();">next>/>id="photo"src="">id="name">Name>>   >   >
For the Body’s onload event, we assigned a loadData handler. This creates the service and downloads the data. There are two links to handle for moving to the next or previous image, with event handlers assigned, and finally an image and a paragraph with specific IDs assigned to hold the data.

Inside the main.js File

All the JavaScript that makes our widget work is contained in the main.js file. At the very top we declare our workersTable variable that gets defined in the connectToService function.

The createServices function actually contains two other functions. The first is includeScript, which is used to include DataAbstract.js and DataAbstract4_intf.js scripts when the call is made to connectToService, the second function in the createServices function. You’ll recognize this pattern and the includeScript function from the RemObjects SDK widget, and you will want to include them in your widgets.

The code you will customize in your own widgets is in the connectToService function, but most of it will be similar.

function createServices(){   function includeScript(scriptSrc, callback){var headID = document.getElementsByTagName("head")[0];var newScript = document.createElement('script'); newScript.type='text/javascript'; newScript.onload= callback; newScript.src= scriptSrc; headID.appendChild(newScript);}   function connectToService(){// Use a different server here if you like:var Channel =new RemObjects.SDK.HTTPClientChannel("http://www.remobjects.com:8099/JSON");// Must be JSONMessage - BinMessage doesn't work in Safarivar Message =new RemObjects.SDK.JSONMessage();var Service =new RemObjects.SDK.RemoteService(Channel, Message,"DASampleService");var daService =new DataAbstractService(Service);var loginService =new RemObjects.SDK.RemoteService(Channel, Message,"LoginService");var Adapter =new RemObjects.DataAbstract.RemoteDataAdapter(Service, loginService, RemObjects.DataAbstract.Bin2DataStreamer); Adapter.onLoginNeeded=function(aCallback){this.login("John","John",function(msg){if(aCallback) aCallback();}, RemObjects.UTIL.ShowError);} workersTable =new RemObjects.DataAbstract.DataTable("workers");   // Get the data Adapter.getData([workersTable], RemObjects.DataAbstract.Util.createRequestInfo(true,-1,'',[]),function(){// This is executed when the data comes back. workersTable.first(); displayImage();}, RemObjects.UTIL.showError);   } includeScript("DataAbstract.js",function(){ includeScript("DataAbstract4_intf.js", connectToService())});}
The connectToService function creates the following:
  1. Channel –This is the connection to the remote server.
  2. Message – The message used as transport. Remember it needs to be JSON since Safari doesn’t like BinMessage.
  3. Service – This is the specific RemObjects SDK service on the channel we are using.
  4. daService – This is the Data Abstract service that uses the RemObjects SDK service.
  5. loginService – This service handles login, if necessary.
  6. Adapter – Provides access to the data tables.
  7. workersTable – The DataTable that contains the data from the Workers table on the remote server.

In this example, it grabs the entire Workers table, but we could just as easily use DA/SQL here to only grab the parts of the table we are interested in.

The displayImage function simply displays the current image and name in the appropriate HTML elements on the page. It gets these values from the Workers Table.

function displayImage(){ document.getElementById("photo").src="data:image/jpeg;base64,"+ RemObjects.UTIL.toBase64(workersTable.getFieldValue("workerphoto")); document.getElementById("name").innerText= workersTable.getFieldValue("WorkerLastName")+", "+ workersTable.getFieldValue("WorkerFirstName");}
The **showNext** and **showPrev** functions move through the Workers Table and call displayImage to update the display.
function showNext(){ workersTable.next(); displayImage();}   function showPrevious(){ workersTable.prev(); displayImage();}
And that is all the JavaScript specific to this widget.

Deploying to iBooks

If you’ve already put all these files into a folder and renamed the folder with the .wdgt extension, you are ready to include the package in an iBook. Just add an HTML widget to your iBook and drag the widget package into it (or use the Choose… button from the Widget Inspector).

Be sure your iPad has access to the server and port www.remobjects.com:8099 since that is where the data is pulled from.

Summary

Data Abstract’s JavaScript client library brings the power of remote databases to your iBooks interactive widgets.

Things to Remember

  1. All the scripts must be included in the widget package.
  2. All JavaScript libraries must be referenced from the Main HTML file.
  3. Use the includeScript function to include library scripts.
  4. Don’t leave any JavaScript alert statements in from debugging. They lock up iBooks.