This is the 4th article in a 4 part series (the last for now)
- Using DashCode to create an interactive widget
- Creating an interactive widget without Dashcode
- Creating a RemObjects SDK client widget
- 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).
- RemObjectsSDK.js – The RemObjects SDK JavaScript library used by Data Abstract.
- DataAbstract4_intf.js – The Data Abstract interface class used by RemObjects SDK for Data Abstract.
- DataAbstract.js – The Data Abstract JavaScript library.
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"/> >>>> rel="stylesheet"href="ro.css"type="text/css"/>> |
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> |
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())});} |
- Channel –This is the connection to the remote server.
- Message – The message used as transport. Remember it needs to be JSON since Safari doesn’t like BinMessage.
- Service – This is the specific RemObjects SDK service on the channel we are using.
- daService – This is the Data Abstract service that uses the RemObjects SDK service.
- loginService – This service handles login, if necessary.
- Adapter – Provides access to the data tables.
- 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");} |
function showNext(){ workersTable.next(); displayImage();} function showPrevious(){ workersTable.prev(); displayImage();} |
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
- All the scripts must be included in the widget package.
- All JavaScript libraries must be referenced from the Main HTML file.
- Use the includeScript function to include library scripts.
- Don’t leave any JavaScript alert statements in from debugging. They lock up iBooks.