Advertisement

Introduction to webOS SDK Development: Part 2

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →
This post is part of a series called Introduction to webOS SDK Development.
Introduction to webOS SDK Development
Introduction to webOS SDK Development: Part 3

In this tutorial, you will learn how to build a webOS application to display all the sites in the tuts+ network. This is the second installment of a series on webOS mobile development. Read part one of this series for a general introduction to the platform and to become familiar with the tools you will need to develop webOS applications.

Create the new application

To get started, open a Command Prompt / Terminal and type the following:

palm-generate tutsplus

This will create the directory "tutsplus" and the necessary directory structure for webOS applications.

Download the images for the tuts+ sites attached to this post. Copy the files into the app/images directory, and then copy tuts_icon.png to the tutsplus directory.

Now we take a closer look at "tutsplus/appinfo.json." Open the appinfo.json file in your favorite text editor and modify it to read as follows:

{
  "id": "com.mycompany.tutsplus",
  "version": "1.0.0",
  "vendor": "MyCompany",
  "type": "web",
  "main": "index.html",
  "title": "TutsPlus",
  "icon": "tuts_icon.png"
}

Go ahead and change the "id" and "vendor" values to your own as well.

Add the first scene

To fill our stage with life we go ahead and create the first, or "main," scene:

palm-generate -t new_scene -p "name=main" tutsplus

This will create two files: the view in app/views/main/main-scene.html and the assistant for the scene at app/assistants/main-assistant.js

Now, open main-scene.html and add the first part, the header:

<div id="myHeader" class="tuts-header palm-page-header multi-line">
    <div id="titleImage" class="title-image">
	    <img src="images/tutsplus.png" />
	    <span class="main-title">Skills to pay the bills </span>
    </div>
</div>

The class "palm-page-header multi-line" is one of many included with the Mojo Framework, but we are going to define the additional classes found in the HTML snippet above ourselves. Edit stylesheet/tutsplus.css for that and add these class definitions:

.tuts-header {
    position: fixed;
    z-index: 1000;
    width: 100%;
    height: 35px;
    padding: 10px 0 0;
    margin: 0;
    -webkit-palm-mouse-target: ignore;
}

.title-image {
    position: fixed;
    top: 16px;
    left: 14px;
}

.main-title {
    position: absolute;
    font-size: 24px;
    left: 60px;
    top: -4px;
    width: 220px;
}

As you can see, we use standard CSS properties with one exception:

-webkit-palm-mouse-target: ignore;

This non-standard property tells the header to ignore clicks.

NOTE:
What if you want to look at the DOM elements and CSS styles of your application? Use the palm-inspector.

We now add the meat of our application to the scene, a list widget:

<div class="palm-list main-list">
    <div id="MyList" x-mojo-element='List'></div>
</div>

Lists

Let's dive into lists for a moment. Lists are probably the most used widget in webOS. They allow us to display data in columns and much more. webOS Lists include the following functionality:

  • Swipe to delete
  • Reordering
  • Built-in "Add New" Feature
  • Templarized layout
  • Dynamic rendering
  • Much more

We head over to app/assistants/main-assistant.js to setup our scene and the list it contains. First we define the necessary data to fill our list:

MainAssistant.prototype.setup = function() {

/* this function is for setup tasks that have to happen when the scene is first created */
/* use Mojo.View.render to render view templates and add them to the scene, if needed */

/* setup widgets here */

/* add event handlers to listen to events from widgets */

  this.myListModel = { items : [
	{ title : 'Nettuts', titleImage : 'images/nettuts.png', leftImage : 'images/tiny-net.jpg', col : '#2e6a60'},
	{ title : 'Vectortuts', titleImage :'images/vectortuts.png', leftImage : 'images/tiny-vector.jpg', col : '#19487e'},
	{ title : 'Psdtuts', titleImage : 'images/psdtuts.png', leftImage : 'images/tiny-psd.jpg', col : '#a51500' },
	{ title : 'Activetuts', titleImage : 'images/activetuts.png', leftImage : 'images/tiny-active.jpg', col : '#a5290a'},
	{ title : 'Aetuts', titleImage :'images/aetuts.png', leftImage : 'images/tiny-ae.jpg', col : '#4a3a57'},
	{ title : 'Cgtuts', titleImage :'images/cgtuts.png', leftImage : 'images/tiny-cg.jpg', col : '#73434f'},
	{ title : 'Phototuts', titleImage :'images/phototuts.png', leftImage : 'images/tiny-photo.jpg', col : '#2e92b2'},
	{ title : 'Audiotuts', titleImage :'images/audiotuts.png', leftImage : 'images/tiny-audio.jpg', col : '#3d6b00'},
	{ title:  'Mobiletuts', titleImage: 'images/mobiletuts.png', leftImage: 'images/tiny-mobile.png', col : '#d19c00' }
  ] };

Note that myListModel has a property named "items." The List widget expects to find a property in the dataModel that contains an array of objects. This property name must be "items." In our case, we define the information about the tutsplus network. Each item contains properties representing the title,images and color for each site. These properties can be used in the list by including it in the list template. A list is rendered with the help of a template, so let's go ahead and create ours: app/views/main/itemTemplate.html. Edit the new template to contain the following:

<div class="palm-row grid-cell" x-mojo-tap-highlight="immediate">
    <div class="title"><img src="#{leftImage}"> #{title}</div>
</div>

Our template tells the list how to display each item from its model. We want to display the title and image from our model, so we include the special tags #{leftImage} and #{title}. Those get replaced with the data out of our model when the row is rendered.

Next, add the class "grid-cell" to the stylesheet stylesheets/tutsplus.css:

.grid-cell {
   color: #000;
}

.grid-cell.selected {
   color: #fff;
   background: #ccc;
   border: 1px solid #00f;
}

Those two classes define the look of a list row in it's unselected and selected state.

Go back to app/assistants/main-assistant.js and add the necessary statement to setup our list:

this.myListAttr = {
    itemTemplate: "main/itemTemplate",
    renderLimit: 20,
};

this.controller.setupWidget("MyList",this.myListAttr,this.myListModel);

};

In myListAttr we tell the list which template to use; we specifiy our just created template. As you can see in the setupWidget call, we pass the id of the list, the parameters, and the model.

We also need to edit app/assistants/stage-assistant.js to display the main scene when the application starts:

function StageAssistant() {
	/* this is the creator function for your stage assistant object */
}

StageAssistant.prototype.setup = function() {
	/* this function is for setup tasks that have to happen when the stage is first created */
	Mojo.Controller.stageController.pushScene("main");
};

First run

All done, let's see what our application looks like .. launch the emulator, package the application and install it to the emulator:

palm-package tutsplus
palm-install com.mycompany.tutsplus_1.0.0_all.ipk

Looking pretty good, don't you think? All that with just a few lines of code. Let's add some more functionality. What about something that happens when the user clicks on a row in the list? Allright, go ahead and add the following to app/assistants/main-assistant.js:

MainAssistant.prototype.activate = function(event) {

/*  put in event handlers here that should only be in effect when this scene is active. For
    example, key handlers that are observing the document */

    this.tapHandler = this.handleTap.bindAsEventListener(this);
    Mojo.Event.listen(this.controller.get('MyList'),Mojo.Event.listTap, this.tapHandler);

};

MainAssistant.prototype.handleTap = function(event) {
  Mojo.Log.info("Event index is: " + event.index);
  Mojo.Log.info("selected: "+event.item.title);

  this.title=event.item.title;
  this.titleImage=event.item.titleImage;
  this.col=event.item.col;

  Mojo.Controller.stageController.pushScene("list" , this.title, this.titleImage, this.col);

}

Logging: As you see above, we added a Mojo.Log.info statement to the code. Sometimes, your app won't start or work or you just want to print out some debuggin information. Mojo.Log.info will help you do that. To see the output produced by Mojo.Log.info, use the command:

palm-log <appid>

(com.mycompany.tutsplus for our application)

This time, we add the Mojo.Event.listen call to the activate method of the MainAssistant. Each time the app gets activated (scene is pushed or another scene is popped and our scene is show again) the code in activate is called.

We create a handler (this.taphandler) and call it when we detect a tap (Mojo.Event.listTap) on our list (this.controller.get('MyList')

Let's look at our handler handleTap function. When the list is tapped, the function receives an even object. What we are interested in is the event.index property, which contains which row of the list was tapped. Luckily for us, the event object also contains the properties of the tapped's row item taken from the model. event.item.title as an example will contain "Mobiletuts" if we click on that row.

We collect all the data we want to use out of the event object and finally call our new scene "list." Note how we append the data we want to pass on to this scene in the pushScene call. You can append as many parameters as you want.

MainAssistant.prototype.deactivate = function(event) {
    /*  remove any event handlers you added in activate and do any other cleanup that should happen before
        this scene is popped or another scene is pushed on top */

    Mojo.Event.stopListening(this.controller.get('MyList'),Mojo.Event.listTap, this.tapHandler);
};

Note that we also add a Mojo.Event.stopListening to the deactivate method of MainAssistant. That way, our App doesn't listen to taps on the list anymore when a different scene is pushed on top on it and we don't run into any stray Eventhandlers when the App is exited.

What still needs to be done is to create the new scene list:

palm-generate -t new_scene -p "name=list" tutsplus

Next, edit app/views/list/list-scene.html:

<div id="image"></div>
<div id="result"></div>

Now edit app/assistant/list-assistant.js:

function ListAssistant(title, titleimage, col) {
    /*  this is the creator function for your scene assistant object. It will be passed all the
        additional parameters (after the scene name) that were passed to pushScene. The reference
        to the scene controller (this.controller) has not be established yet, so any initialization
        that needs the scene controller should be done in the setup function below. */

        this.title=title;
        this.titleimage=titleimage;
        this.col=col;
}

ListAssistant.prototype.setup = function() {
	/* this function is for setup tasks that have to happen when the scene is first created */

	/* use Mojo.View.render to render view templates and add them to the scene, if needed */

	/* setup widgets here */

	/* add event handlers to listen to events from widgets */

 	this.controller.get('result').innerHTML="You have selected "+this.title+" in the list."
 	this.controller.get('image').innerHTML="<img src="+this.titleimage+">"

}

Note how we copy the passed in parameters into new variables for later use. We also update our scene's HTML to show those passed in parameters.

Repackage the app, install and run it. Tap a list row and see how the new scene is pushed and displays which row you selected!

Wrap up

Congratulations, we covered quite a range of topics in this second part. You learned how to create a list, fill it with data, display it, and then react to user interaction. In the next part, we are going to fill our list scene with functionality: get the latest tutorials and articles from the RSS feed of the selected site and display them in a list. We hope you stick around, and leave your feedback in the comments section!

Advertisement