<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WebOS Boston &#187; Tutorials</title>
	<atom:link href="http://www.webosboston.org/category/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.webosboston.org</link>
	<description>Developing for WebOS</description>
	<lastBuildDate>Fri, 13 Nov 2009 23:03:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Mojo Lists: Using the Depot as a Data source (Part 4)</title>
		<link>http://www.webosboston.org/2009/10/11/mojo-lists-using-the-depot-as-a-data-source-part-4/</link>
		<comments>http://www.webosboston.org/2009/10/11/mojo-lists-using-the-depot-as-a-data-source-part-4/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 22:39:11 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mojo]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Depot]]></category>
		<category><![CDATA[Lists]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=238</guid>
		<description><![CDATA[In this tutorial we are going to cover using the Depot as a data source for a list.  We will be expanding on the code written in the previous parts of this tutorial listed below.
Part 1: Mojo Lists
Part 2: Mojo Lists: Using a Cookie as a Data Source
Part 3: Mojo Lists: Restructuring our Code
If [...]]]></description>
			<content:encoded><![CDATA[<p>In this tutorial we are going to cover using the Depot as a data source for a list.  We will be expanding on the code written in the previous parts of this tutorial listed below.</p>
<p>Part 1: <a href="http://www.webosboston.org/2009/09/13/mojo-lists-part-1/">Mojo Lists</a><br />
Part 2: <a href="http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/">Mojo Lists: Using a Cookie as a Data Source</a><br />
Part 3: <a href="http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/">Mojo Lists: Restructuring our Code</a></p>
<p>If you were able to follow along with using the cookie as a data source this is going to be relatively easy for you to integrate into the existing code.  </p>
<p><span id="more-238"></span><br />
The first thing that I know we will create is the WBDepot model so we will open up our sources.json file and add that right after our WBCookie model.</p>
<pre name="code" class="javascript">
[
    {"source": "app\/lib\/utils.js"},
    {"source": "app\/lib\/WBModel.js"},
    {"source": "app\/lib\/WBBase.js"},
    {"source": "app\/lib\/WBCookie.js"},
    {"source": "app\/lib\/WBDepot.js"},
    {"source": "app\/assistants\/stage-assistant.js"},
    {
        "source": "app\/assistants\/main-assistant.js",
        "scenes": "main"
    },
    {
        "source": "app\/assistants\/cookie-assistant.js",
        "scenes": "cookie"
    },
    {
        "source": "app\/assistants\/depot-assistant.js",
        "scenes": "depot"
    },
    {
        "source": "app\/assistants\/sqlite-assistant.js",
        "scenes": "sqlite"
    },
    {
        "source": "app\/assistants\/altervalue-assistant.js",
        "scenes": "altervalue"
    }
]
</pre>
<p>Now we need to actually create the file for our WBDepot model so create the file /lib/WBDepot.js and add the following code.</p>
<pre name="code" class="javascript">
// Inherit the WBBase object
WBDepot.prototype = new WBBase;

function WBDepot() {
    var options = { name: 'wb_depot_list_demo', version: 1, replace: false, estimatedSize: 100000 };
    this.depot = new Mojo.Depot(options, this.openSuccess.bind(this), this.openFailure.bind(this));
}

/**
 * Public methods that need to exist in all of our model objects, these override the methods in WBBase
 * Think of these as abstract methods.
 */
WBDepot.prototype.save = function(listContents)
{
    Mojo.Log.info("Depot save started.");
    this.depot.add(
        'listContents',
        listContents,
        this.saveContentsSuccess.bind(this),
        this.saveContentsFailure.bind(this)
    );
};

/**
 * Methods that belong solely to the WBDepot object, these are only called internally and never called on the object instance
 */
WBDepot.prototype.openSuccess = function() {
    Mojo.Log.info("Depot opened successfully");
    this.depot.get(
        "listContents",
        this.loadDepotContents.bind(this),
        this.loadDefaultContents.bind(this)
    );
};

WBDepot.prototype.openFailure = function(result) {
    Mojo.Log.warn("Unable to open depot: ", result);
};

WBDepot.prototype.loadDepotContents = function(result) {
    if(result === null) {
        Mojo.Log.warn("Retrieved empty or null contents from the depot, using defaults.");
        this.loadDefaultContents();
    } else {
        Mojo.Log.info("Retrieved contents from the depot.");
        this.list = result;
    }
};

WBDepot.prototype.loadDefaultContents = function() {
    Mojo.Log.info("Loading default contents");
    this.contents = this.defaultContents;
};

WBDepot.prototype.saveContentsSuccess = function() {
    Mojo.Log.info("Contents saved to the depot.");
};

WBDepot.prototype.saveContentsFailed = function(result) {
  Mojo.Log.warn("Depot save failed: ", result);
};
</pre>
<p>At first look this might seem like a confusing object because it has quite a few more methods than our WBCookie object.  This is not true it just has to have these methods due to the asynchronous nature of the depot.  In the constructor you will notice that we create our connection to the depot.  We pass in the options and a success and failure callback methods.  If the depot is opened successfully it calls the success method otherwise it calls the failed method.  In the success method we log an entry to our log and then try to fetch the contents from our depot for the key 'listContents'.  Again you will notice that we have passed in some callback methods.  If it is successful in fetching the data from the depot it calls the loadDepotContents method otherwise it will call the loadDefaultContents method.  Basically it boils down to it will either fetch the contents of our list from the depot or it will load our default contents.  You will also notice that this object inherits from the WBBase object we created in <a href="http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/">Part 3</a>.  If you are wondering where the this.defaultContents is coming from recall that in the WBBase object we have the defaultListContents defined and since WBDepot inherits from WBBase it is able to use the values defined there.  You will also see some methods in there which are used as callback in the save method.</p>
<p>So with our model in place we now have to work on our depot-assistant.js file and the associated view files.  Make your depot-assistant.js look like my code below.</p>
<pre name="code" class="javascript">
function DepotAssistant() {
    this.listModel = {};
    this.model = null;
}

DepotAssistant.prototype.setup = function() {
    this.model = new WBModel('depot');

    this.listModel = {
	items: {}
    };

	Mojo.Log.info("listModel: %j", this.listModel);

    this.controller.setupWidget("depotListWgt",
        {
            itemTemplate: "depot/depotRowTemplate",
            listTemplate: "depot/depotListTemplate",
            swipeToDelete: false,
            renderLimit: 40,
            reorderable: false
        },
	this.listModel
    );
    this.depotListHandler = this.loadAlterValueScene.bindAsEventListener(this);
    this.controller.listen(this.controller.get("depotListWgt"), Mojo.Event.listTap, this.depotListHandler);
};

DepotAssistant.prototype.loadAlterValueScene = function(event)
{
    Mojo.Controller.stageController.pushScene( 'altervalue', 'depot', event.index, this.listModel.items );
};

DepotAssistant.prototype.activate = function(event) {
	this.listModel.items = this.model.getListContents();
	this.controller.modelChanged(this.listModel);
};

DepotAssistant.prototype.deactivate = function(event) {

};

DepotAssistant.prototype.cleanup = function(event) {
	Mojo.Event.stopListening(this.controller.get("depotListWgt"), Mojo.Event.listTap, this.depotListHandler);
};
</pre>
<p>If you look at the code above and compare it to our cookie-assistant.js file you will see that very little has changed.  We changed the instances of the word cookie to depot and that is it.  You should be starting to see why I introduced the restructuring of the code in <a href="http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/">Part 3</a>.  It makes it ridiculously simple to add another data source for our lists.  So now that we have the assistant out of the way we need to create our view files so create the following files.</p>
<pre name="code" class="html">
&lt;!-- views/depot/depot-scene.html --&gt;
<div id="feedTitle" class="palm-header center"> Depot List
</div>
<div class="palm-header-spacer"></div>
<div id="mainScene" class="mainScene">
<div x-mojo-element="List" id="depotListWgt" ></div>
</div>
</pre>
<pre name="code" class="html">
&lt;!-- views/depot/depotListTemplate.html --&gt;
<div class="palm-list">#{-listElements}</div>
</pre>
<pre name="code" class="html">
&lt;!-- views/depot/depotListTemplate.html --&gt;
<div class="palm-row" x-mojo-touch-feedback="delayed">
<div class="palm-row-wrapper">
<div id="itemTitle" class="title truncating-text">#{title}</div>
</div>
</div>
</pre>
<p>With these files in place we are almost ready to start using our depot list.  There are a few more changes we need to make though.  We need to go back to our WBModel.js object and allow for the depot storage type.  Make your WBModel object look like the code below.</p>
<pre name="code" class="javascript">
function WBModel(storageType)
{
  /*
   * Default storageType
   *
   * This is set so that if the developer does not send in a storageType type value it will default to a cookie.
   * It will also default to cookie if the storageType type specified is not in our supported list of supported storageType types.
   */
  this.defaultStorageType = 'cookie';
  this.supportedStorageTypes = ['cookie', 'depot'];

  // set the initial storageType type to the default storageType type
  this.storageType = this.defaultStorageType;

  // check to make sure that our specified storageType type is in our supported storageType types - The in_array function is in our utils.js file.
  if(in_array(storageType, this.supportedStorageTypes))
  {
	// set the storageType type to the specified storageType type.
	this.storageType = storageType;
  }
  else
  {
    Mojo.Log.info("Unsupported storage type '%s' using the '%s' as default", storageType, this.defaultStorageType);
  }

  return this.factory(storageType);
}

WBModel.prototype.factory = function(storageType) {
  switch(this.storageType)
  {
	case 'depot':
	  // Placeholder for Depot Object Instantiation
	  return new WBDepot();
	  break;
	case 'cookie':
	default:
	  // Cookie storage by default
	  return new WBCookie();
  }
}
</pre>
<p>The only changes we have made in the code above is adding the 'depot' to our list of supportedStorageTypes and in the initialize method we have instantiated the model for the depot option.  If you run the code at this point you will be able to work with both the Cookie and Depot lists in our demo application.  In Part 5 will will conclude this series by taking a look at using SqLite for our storage mechanism.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/10/11/mojo-lists-using-the-depot-as-a-data-source-part-4/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mojo Lists: Restructuring our Code (Part 3)</title>
		<link>http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/</link>
		<comments>http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 02:47:17 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mojo]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Lists]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=233</guid>
		<description><![CDATA[In Part 2 of this series we created the ability to use a cookie for a lists data source.  In this part we are going to cleanup our code a bit and try to restructure things so that it is easier to expand on our set of code.
After looking at the code I saw [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/">Part 2</a> of this series we created the ability to use a cookie for a lists data source.  In this part we are going to cleanup our code a bit and try to restructure things so that it is easier to expand on our set of code.</p>
<p>After looking at the code I saw that we created the WBCookie model object that was not very abstract.  We wish to keep things somewhat abstract so that the application is not concerned too much about where the data is coming from.  We are going to be creating a few files that will be in our lib/ directory and I will explain why we are using them and what they do as we continue through the tutorial.</p>
<p>The first thing I want you to do is open up your sources.json file and add 3 lines at the top.  We will want to include the files that we will be creating so that Mojo will know where to find them.  Open your file and make it look like the following.  Note that I only added the first three lines to this file.</p>
<p><span id="more-233"></span></p>
<pre name="code" class="javascript">
[
    {"source": "app\/lib\/utils.js"},
    {"source": "app\/lib\/WBModel.js"},
    {"source": "app\/lib\/WBBase.js"},
    {"source": "app\/lib\/WBCookie.js"},
    {"source": "app\/assistants\/stage-assistant.js"},
    {
        "source": "app\/assistants\/main-assistant.js",
        "scenes": "main"
    },
    {
        "source": "app\/assistants\/cookie-assistant.js",
        "scenes": "cookie"
    },
    {
        "source": "app\/assistants\/depot-assistant.js",
        "scenes": "depot"
    },
    {
        "source": "app\/assistants\/sqlite-assistant.js",
        "scenes": "sqlite"
    },
    {
        "source": "app\/assistants\/altervalue-assistant.js",
        "scenes": "altervalue"
    }
]
</pre>
<p>We have also created a utility function named in_array which works just like that function in PHP.  JavaScript does not have this capability natively so we needed to add it for our use.  Create the utils.js file under our lib/ directory and make it have the following code.</p>
<pre name="code" class="javascript">
/* Utility Functions */

function in_array (needle, haystack, argStrict) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: vlado houba
    // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: true
    // *     example 2: in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});
    // *     returns 2: false
    // *     example 3: in_array(1, ['1', '2', '3']);
    // *     returns 3: true
    // *     example 4: in_array(1, ['1', '2', '3'], false);
    // *     returns 4: true
    // *     example 5: in_array(1, ['1', '2', '3'], true);
    // *     returns 5: false

    var key = '', strict = !!argStrict;

    if (strict) {
        for (key in haystack) {
            if (haystack[key] === needle) {
                return true;
            }
        }
    } else {
        for (key in haystack) {
            if (haystack[key] == needle) {
                return true;
            }
        }
    }

    return false;
}
</pre>
<p>Now that we have our utils.js out of the way it is time to create your WBModel.js file under lib/ and make it look like the following.</p>
<pre name="code" class="javascript">
function WBModel(storageType)
{
  /*
   * Default storageType
   *
   * This is set so that if the developer does not send in a storageType type value it will default to a cookie.
   * It will also default to cookie if the storageType type specified is not in our supported list of supported storageType types.
   */
  this.defaultStorageType = 'cookie';
  this.supportedStorageTypes = ['cookie'];

  // set the initial storageType type to the default storageType type
  this.storageType = this.defaultStorageType;

  // check to make sure that our specified storageType type is in our supported storageType types - The in_array function is in our utils.js file.
  if(in_array(storageType, this.supportedStorageTypes))
  {
	// set the storageType type to the specified storageType type.
	this.storageType = storageType;
  }
  else
  {
    Mojo.Log.info("Unsupported storage type '%s' using the '%s' as default", storageType, this.defaultStorageType);
  }

  return this.factory(storageType);
}

WBModel.prototype.factory = function(storageType) {
  switch(this.storageType)
  {
	case 'cookie':
	default:
	  // Cookie storage by default
	  return new WBCookie();
  }
}
</pre>
<p>With our new WBModel object we have the ability to use any type of data source we wish to use all we have to do is tell it which one we want.  In the constructor we set the defaultStorageType to be a cookie and we also set the array of our supported storage types.  If palm were to introduce another storage mechanism in the future it would be pretty easy to add it to this application.  The main portion I want to point out is the in_array function call.  JavaScript does not have a native method of checking to see if an item is in an array or not without looping over everything each time.  I added a utility function that I found online called in_array which mimics how PHP's in_array function works.  This allows us to check to make sure that the developer sent in a valid storage type before we try to get very far in the code.  If we do find that a developer is trying to use an unrecognized storage type we write a nice message to the log and use the defaultStorageType instead.</p>
<p>You will notice that we have a factory method for the WBModel object.  This allows us anywhere in our code to call WBModel.factory('depot'); and have it return to us a depot object model. If you would like to read more about this method you can read about <a href="http://www.lovemikeg.com/blog/2009/06/26/the-factory-pattern-in-javascript/">the factory pattern in JavaScript</a>.</p>
<p>So now that we have our WBModel object out of the way it's time to take a look at the last object i have created.  The WBBase object will never actually be instantiated directly. This object is used as the base for all of our model classes and the functionality it provides is inherited by our model classes.  Create the file WBBase.js in your lib directory and put the following code in the file.</p>
<pre name="code" class="javascript">
function WBBase() {
  this.defaultContents =
  [
    {
      title: "Default 1"
    },
    {
      title: "Default 2"
    },
    {
      title: "Default 3"
    }
  ];

  this.contents = [];
}

WBBase.prototype.getListContents = function() {
  return this.contents;
}

WBBase.prototype.setListContents = function(listContents) {
  this.contents = listContents;
}

/**
 * The folowing are methods that should be overridden in the objects that extend from WBBase
 * Think of them as abstract methods.
 */
WBBase.prototype.save = function(listContents) {
  Mojo.Log.error("You have failed to override the save method in your model object.");
};
</pre>
<p>You might notice that this object does not have a lot of code and it does not have to have much because this functionality is inherited.  In the constructor I am setting the defaultContents to be our default items which we hard coded in place.  There are two methods that get inherited and they should be pretty explanatory as they are just for setting and getting the listContents.  There is one method that I want to talk about and that is the save method.  You might be wondering why we have a log line in there stating that you failed to override the save method.  This is because each model object should know how to save it's data this is not something that can be inherited.  I have this method in place here because if a developer fails to put a save method in their model they will have something in the log alerting them to that fact.  This might look familiar to you if you are familiar with abstract methods from other languages.</p>
<p>Now we need to alter our WBCookie object so that it will work with the code we just created.  Open the WBCookie.js file and make it look like the code below.</p>
<pre name="code" class="javascript">
// Inherit from WBBase();
WBCookie.prototype = new WBBase;

function WBCookie()
{
    this.cookie = new Mojo.Model.Cookie('wb_cookie_list_demo');
    this.contents = this.cookie.get('listContents');
    if(this.contents === undefined) {
        this.contents = this.defaultContents;
    }
}

WBCookie.prototype.save = function(listContents)
{
    this.cookie.put(listContents);
};
</pre>
<p>In our WBCookie object we have greatly reduced the code actually necessary for interacting with our cookie.  The first thing I want to note is the very first line where we set the prototype to be assigned a new instance of the WBBase object.  In JavaScript this is just one of the ways that you can tell it you are going to inherit the functionality from the WBBase object.  You can see that we open our cookie in the constructor and set it to this.cookie and in our get method we just grab the data from the cookie.  The final method is the save method and you can see that we accept a parameter.  It is the listContents object which we want to save so we pass it to the this.cookie.put method which puts it in our cookie.  Pretty basic huh!</p>
<p>The final change I made was to rename our altercookie scene and assistant so that it could be used with any of our data storage mechanisms.  Go ahead and rename /assistants/altercookie-assistant.js to /assistants/altervalue-assistant.js and make sure the code looks like the following.</p>
<pre name="code" class="javascript">
function AltervalueAssistant( storageType, index, listContents ) {
    this.itemIndex = index;
    this.listContents = listContents;
    this.storageType = storageType;
}

AltervalueAssistant.prototype.setup = function() {
    this.model = new WBModel(this.storageType);

    /* set up our text field */
    var txtFieldAttributes = {
        hintText: '',
        modelProperty:	'original',
        autoFocus: true
    };
    this.txtFieldModel = {
        'original' : this.listContents[this.itemIndex].title,
        disabled: false
    };

    // Setup our Add Value <a href="http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/" class="alinks_links" onclick="return alinks_click(this);" title="Button">Button</a> and Event Handler
    this.saveBtnAttributes = {};

    this.saveBtnModel = {
        buttonLabel : 'Save',
        buttonClass : 'affirmative',
        disabled : false
    };

    this.controller.setupWidget("save_button", this.saveBtnAttributes, this.saveBtnModel);

    this.controller.setupWidget('textField', txtFieldAttributes, this.txtFieldModel);

    this.saveHandler = this.save.bindAsEventListener(this);
    Mojo.Event.listen(this.controller.get('save_button'), Mojo.Event.tap, this.saveHandler);

};

AltervalueAssistant.prototype.save = function(){
    // change the item and then store the model again
    this.listContents[this.itemIndex].title = this.txtFieldModel.original;
    this.model.setListContents( this.listContents );

    // swap back to the storageType scene
    Mojo.Controller.stageController.popScene();
};

AltervalueAssistant.prototype.activate = function(event) {
    this.txtFieldModel.original = this.listContents[this.itemIndex].title;
    this.controller.modelChanged(this.txtFieldModel);
};

AltervalueAssistant.prototype.deactivate = function(event) {

};

AltervalueAssistant.prototype.cleanup = function(event) {
    Mojo.Event.stopListening(this.controller.get('save_button'), Mojo.Event.tap, this.saveHandler);
};
</pre>
<p>You will also notice that we have not changed this too much other than changing the object name.  We did introduce a few new things and that is that we now pass in the storageType when we make a call to the altervalue object.  This is so that we can actually make sure the proper model is being updated.  We are also passing in the list contents and I am doing this because it is much easier to implement by passing the value in and when we get to <a href="http://www.webosboston.org/2009/10/11/mojo-lists-using-the-depot-as-a-data-source-part-4/">Part 4</a> and using the Depot you will understand why.  In the save event handler I also changed the swapScene to a popScene.  There was a small bug with the way I had it before that caused you to have to swipe back twice rather than once to get back to our main list.  Using popScene rather than swapScene just pulls the alter value scene off the top of the stack.  Next you will need to rename the scene folder and phtml file to be /altervalue/altervalue-scene.phtml.</p>
<p>Now since we changed the swapScene to a pushScene we have introduced another small bug.  When you are on the altervalue scene and hit the button to save the value it does just that.  It saves the value in the proper storage mechanism and then pulls the altervalue scene off the top of the stack.  The scene you see now is the cookie-scene showing the list of values stored in the cookie.  However the bug is caused because you never update the cookie-scene to tell it that the model data has been changed.  We need to add some code to our assistant's activate method so that when the scene is activated we update the view with the data from our model.  Please make your cookie-assistant.js file look like the following.</p>
<pre name="code" class="javascript">
function CookieAssistant() {
    this.listModel = {};
    this.model = null;
}

CookieAssistant.prototype.setup = function() {
    this.model = new WBModel('cookie');

    this.listModel = {
		items: this.model.getListContents()
    };

    this.controller.setupWidget("cookieListWgt",
        {
            itemTemplate: "cookie/cookieRowTemplate",
            listTemplate: "cookie/cookieListTemplate",
            swipeToDelete: false,
            renderLimit: 40,
            reorderable: false
        },
		this.listModel
    );
    this.cookieListHandler = this.loadAlterValueScene.bindAsEventListener(this);
    this.controller.listen(this.controller.get("cookieListWgt"), Mojo.Event.listTap, this.cookieListHandler);
};

CookieAssistant.prototype.loadAlterValueScene = function(event)
{
    Mojo.Controller.stageController.pushScene( 'altervalue', 'cookie', event.index, this.listModel.items );
};

CookieAssistant.prototype.activate = function(event) {
	this.listModel.items = this.model.getListContents();
	this.controller.modelChanged(this.listModel);
};

CookieAssistant.prototype.deactivate = function(event) {

};

CookieAssistant.prototype.cleanup = function(event) {
	Mojo.Event.stopListening(this.controller.get("cookieListWgt"), Mojo.Event.listTap, this.cookieListHandler);
};
</pre>
<p>You can see that we have changed this quite a bit since <a href="http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/">Part 2</a> of this series.  First in our setup method we are instanciating our WBCookie object and storing it in the this.cookie property.  We are then calling the getListContents method on our WBCookie object and using that as the items for our listModel.  The next thing we did was rename the loadAlterCookieScene method to loadAlterValueScene so that we conform to the changes we made earlier.  The rest of the code has remained the same.  Now that we have our alterations out of the way you should be able to run this in the emulator and work your way through the cookie list as you could in the end of <a href="http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/">Part 2</a>.  You may be asking why the heck we did all of these alterations to our code when we have not yet introduced any new functionality.  Well the reason is because after looking at the code planning out this part of the series I thought we could make it much cleaner by using this method.  Now all we have to do in order to add a new storage mechanism is create the object code and alter our WBModel.js object to allow for that storageType.</p>
<p>With these changes out of the way we are free to move on and add more storageTypes which we will cover in the next part of this series.  <a href="http://www.webosboston.org/2009/10/11/mojo-lists-using-the-depot-as-a-data-source-part-4/">Part 4</a> will show you how to use the depot as a storage mechanism.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mojo Lists: Using a Cookie as a Data Source (Part 2)</title>
		<link>http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/</link>
		<comments>http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 23:36:21 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mojo]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Cookie]]></category>
		<category><![CDATA[Lists]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=173</guid>
		<description><![CDATA[In Part 1 of this tutorial we created the base for our application.  It consisted of a static list that was displayed when the application was launched.  
At the end of Part 1 you were able to build the application and tap on any of the items which would push another scene.  [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.webosboston.org/wp-content/uploads/2009/09/Screen-shot-2009-09-21-at-7.49.39-PM.png" alt="Mojo Lists Part 2" title="Mojo Lists Part 2" width="221" height="332" class="floatleft" />In <a href="http://www.webosboston.org/2009/09/13/mojo-lists-part-1/">Part 1</a> of this tutorial we created the base for our application.  It consisted of a static list that was displayed when the application was launched.  </p>
<p>At the end of Part 1 you were able to build the application and tap on any of the items which would push another scene.  In Part 2 of this tutorial we are going to focus on using a cookie as a data source for our list.  We will build a list that will display a list based on a cookie's contents.  </p>
<p>When you tap on a list item you will be taken to another scene where you will be able to change the title for the list item and it will be retained in a cookie.  I did find an issue with cookies on the emulator and device.  There is a known bug that cookies will retain on the emulator and device even after the application is removed.  To learn more about this issue and cookies I suggest you read the <a href="http://www.webosboston.org/2009/08/28/working-with-cookies/">Working with Cookies</a> tutorial.</p>
<p>We will be continuing with the code that we created in <a href="http://www.webosboston.org/2009/09/13/mojo-lists-part-1/">Part 1</a> so open that application up.  We will first be creating a model object that we will use to interact with the Mojo cookie stuff.  In your application create the folder /app/lib/ and then create a new file named WBCookie.js and put it in your newly created lib folder.  Now you will also have to update your sources.json so that Mojo will know where to find this file.  Be sure that your sources.json file looks like the code below.</p>
<pre name="code" class="javascript">
[
    { "source": "app\/lib\/WBCookie.js" },
    {"source": "app\/assistants\/stage-assistant.js"},
    {
        "source": "app\/assistants\/main-assistant.js",
        "scenes": "main"
    },
    {
        "source": "app\/assistants\/cookie-assistant.js",
        "scenes": "cookie"
    },
    {
        "source": "app\/assistants\/depot-assistant.js",
        "scenes": "depot"
    },
    {
        "source": "app\/assistants\/sqlite-assistant.js",
        "scenes": "sqlite"
    }
]
</pre>
<p><span id="more-173"></span><br />
Now that we have told Mojo where our model file is going to be it's time to start working with our model.  Open your WBCookie.js file and make it look like the code below.</p>
<pre name="code" class="javascript">
function WBCookie()
{
    this.initialContents = [
        {
            title: "Default 1"
        },
        {
            title: "Default 2"
        },
        {
            title: "Default 3"
        }
    ];

    this.listContents = {};
    this.cookie = null;
}

WBCookie.prototype.initialize = function()
{
    this.cookie = new Mojo.Model.Cookie('wb_cookie_list_demo');
    this.storedListItems = this.cookie.get();
    this.listContents = this.initialContents;

    if(this.storedListItems)
    {
        this.listContents = this.storedListItems;
    }

    this.storeCookie();
};

WBCookie.prototype.setListContents = function( listContents )
{
    this.listContents = listContents;
    this.storeCookie();
};

WBCookie.prototype.getListContents = function()
{
    return this.listContents;
};

WBCookie.prototype.storeCookie = function()
{
    this.cookie.put(this.listContents);
};
</pre>
<p>The code above will take a bit of explaining however it works in much the same way as an assistant object.  When the object is created the WBCookie() function is called and we setup a few properties.  We first set the initial contents of what our list will contain.  This is so that we have something to load up the first time before the cookie is even written.  We then declare the listContents as an empty object and set this.cookie to null.  Once the object is created we will call the initialize method.  This is where quite a bit of the magic happens.  The first thing it does is create a new cookie model and set it to this.cookie.  The next line of code grabs the contents of the cookie model and stores that in the storedListItems property.  Notice that we did not define this property in the constructor, it is due to the if statement called next which checks to see if it is defined.  The storeCookie method is where we actually save the data back into the cookie.</p>
<p>Now that we have the model out of the way we are going to work in the cookie assistant to actually setup the list.  Make your cookie assistant look like the code below.</p>
<pre name="code" class="javascript">
function CookieAssistant() {
    this.listModel = {};
    this.cookie = null;
}

CookieAssistant.prototype.setup = function() {
    this.cookie = new WBCookie();
    this.cookie.initialize();

    this.listModel = {
	items: this.cookie.getListContents()
    };

    this.controller.setupWidget("cookieListWgt",
        {
            itemTemplate: "cookie/cookieRowTemplate",
            listTemplate: "cookie/cookieListTemplate",
            swipeToDelete: false,
            renderLimit: 40,
            reorderable: false
        },
	this.listModel
    );
    this.cookieListHandler = this.loadAlterValueScene.bindAsEventListener(this);
    this.controller.listen(this.controller.get("cookieListWgt"), Mojo.Event.listTap, this.cookieListHandler);
};

CookieAssistant.prototype.loadAlterValueScene = function(event)
{
    Mojo.Controller.stageController.pushScene( 'altercookie', event.index );
};

CookieAssistant.prototype.activate = function(event) {

};

CookieAssistant.prototype.deactivate = function(event) {

};

CookieAssistant.prototype.cleanup = function(event) {
	Mojo.Event.stopListening(this.controller.get("cookieListWgt"), Mojo.Event.listTap, this.cookieListHandler);
};
</pre>
<p>The code for our Cookie Assistant is pretty straight forward.  In-fact much of this code is the same as in our Main Assistant.  In the constructor we set the listModel property to be an empty object and we set this.cookie to be null;  When the setup method is called it instantiates our cookie model object and stores it in this.cookie. It then goes on to call the initialize method on our cookie model and then setup the list for use.  Most of the rest of the code is the same as our Main Assistant, there is one thing I want to mention though and that is in our callback method.  When you click on an item in our Cookie List it calls the loadAlterValueScene method which <strong><em>pushes</em></strong> the new scene.  You will notice here that we are pushing scenes rather than swapping to another scene.  I want to take a minute to explain the difference between swapping and pushing a scene.  You can think of the scenes as a stack of cards.  Every time you push a scene you are placing another card on top.  You can remove the top card to get at the previous card.  This is exactly what is happening when you use the swipe back gesture.  If you swap scenes you are essentially swapping cards.  When you swipe back you go to the previous card.  However it is not the scene before the swap because that scene is replaced.  It is the scene that was below the scene that you swapped with.  In this pushScene call we are passing an extra parameter, this will just be passed through to the scene so that it can be used when we make the alteration to our cookie.  Before we move on we actually have to create the view file and if you recall since we are using a list we will also have to create the template files for our list named cookieRowTemplate and cookieListTemplate.  Go ahead and create these two files now.  Once you have them created make them look like the following.</p>
<pre name="code" class="html">
&lt;!-- cookieListTemplate.phtml --&gt;
&lt;div class=&quot;palm-list&quot;&gt;#{-listElements}&lt;/div&gt;
</pre>
<pre name="code" class="html">
&lt;!-- cookieRowTemplate --&gt;
&lt;div class=&quot;palm-row&quot; x-mojo-touch-feedback=&quot;delayed&quot;&gt;
    &lt;div class=&quot;palm-row-wrapper&quot;&gt;
        &lt;div id=&quot;itemTitle&quot; class=&quot;title truncating-text&quot;&gt;#{title}&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>I am not going to explain these files again as I have already gone over them in past tutorials.  Once these are in place it is time to make our cookie-scene.html file look like the code below.</p>
<pre name="code" class="html">
&lt;!-- cookie-scene.html --&gt;
&lt;div id=&quot;feedTitle&quot; class=&quot;palm-header center&quot;&gt; Cookie List
&lt;/div&gt; &lt;div class=&quot;palm-header-spacer&quot;&gt;&lt;/div&gt; &lt;div id=&quot;mainScene&quot; class=&quot;mainScene&quot;&gt;
&lt;div x-mojo-element=&quot;List&quot; id=&quot;cookieListWgt&quot; &gt;&lt;/div&gt; &lt;/div&gt;
</pre>
<p>If you were to save all of your files and run this application on the emulator everything will work fine.  You will see the main list load up and display your options of Cookie, Depot or SqLite.  Currently the only one that will do anything when clicked on is the Cookie item.  When you click on this it pushes you to another scene which shows a list and is populated with our cookie.  If you recall when we first load this up we get the default list items which we defined in the WBCookie object.  However when you tap on an item in our cookie list we have begun setting the stage for an another scene to be pushed.  The idea is that when you are on viewing the cookie list you should be able to tap on any item and be taken to the altercookie view which will have a textbox and a button.  When you alter the text in the textbox and tap the button the value should be saved to our cookie and then we should be passed back to the cookie scene where we will be able to see the changes made.</p>
<p>With the cookie assistant all working the way we want it to it's time to create the final scene for this part of the tutorial.  We are going to create a scene named altercookie which will actually change the data in our cookie.  Once you have the scene created you need to make the altercookie-scene file look like the code below.</p>
<pre name="code" class="html">
&lt;div id=&quot;main&quot; class=&quot;palm-hasheader&quot;&gt;
    &lt;div class=&quot;palm-header left&quot; id=&quot;list-header&quot;&gt;
        Cookie: Alter Value
    &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;palm-group&quot;&gt;
    &lt;div class=&quot;palm-list&quot;&gt;
        &lt;div class=&quot;palm-row single&quot;&gt;
            &lt;div class=&quot;palm-row-wrapper textfield-group&quot; x-mojo-focus-highlight=&quot;true&quot;&gt;
                &lt;div class=&quot;title&quot;&gt;
                    &lt;div id=&quot;textField&quot; name=&quot;textField&quot;  x-mojo-element=&quot;TextField&quot;&gt;&lt;/div&gt;
		&lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;save_button&quot; name=&quot;save_button&quot; x-mojo-element=&quot;Button&quot;&gt;Save&lt;/div&gt;
</pre>
<p>In the code above we are not doing anything too extreme.  You will see that the scene has a header which uses some palm style classes.  We also have a palm-group which is a way to group multiple elements together.  The final element on the scene is a button.  Now we just need to wire these up in our altercookie assistant and make them work together.  Make your altercookie-assistant.js file look like the code below.</p>
<pre name="code" class="javascript">
function AltercookieAssistant( index ) {
    this.itemIndex = index;
}

AltercookieAssistant.prototype.setup = function() {
    this.cookie = new WBCookie();
    this.cookie.initialize();
    this.listContents = this.cookie.getListContents();

    /* set up our text field */
    var txtFieldAttributes = {
        hintText: '',
        modelProperty:	'original',
        autoFocus: true
    };

    this.txtFieldModel = {
        'original' : this.listContents[this.itemIndex].title,
        disabled: false
    };

    // Setup our Add Value Button and Event Handler
    this.saveBtnAttributes = {};

    this.saveBtnModel = {
        buttonLabel : 'Save',
        buttonClass : 'affirmative',
        disabled : false
    };

    this.controller.setupWidget("save_button", this.saveBtnAttributes, this.saveBtnModel);

    this.controller.setupWidget('textField', txtFieldAttributes, this.txtFieldModel);

    this.saveHandler = this.save.bindAsEventListener(this);
    Mojo.Event.listen(this.controller.get('save_button'), Mojo.Event.tap, this.saveHandler);

};

AltercookieAssistant.prototype.save = function(){
    // change the item and then store the cookie again
    this.listContents[this.itemIndex].title = this.txtFieldModel.original;
    this.cookie.setListContents( this.listContents );
    this.storeCookie();

    // swap back to the cookie scene
    Mojo.Controller.stageController.swapScene( 'cookie' );
};

AltercookieAssistant.prototype.activate = function(event) {

};

AltercookieAssistant.prototype.deactivate = function(event) {

};

AltercookieAssistant.prototype.cleanup = function(event) {
    Mojo.Event.stopListening(this.controller.get('save_button'), Mojo.Event.tap, this.saveHandler);
};
</pre>
<p>In the AltercookieAssistant code we are doing pretty much the same stuff we have been doing all along in this tutorial.  The part that is different is that rather than using a list we have used two other Mojo Widgets.  The button and the text field widgets are setup just like a lot of Mojo Widgets are.  You provide them with an attributes object and a model object and then call the setupWidget method to get them setup.  In the code above we have the constructor which is something new for us.  Remember when we made the swapScene call in our Cookie Assistant for the altercookie scene?  We passed in that extra parameter.  </p>
<p>The parameter was the index number of the item we wanted to alter and that was passed into the constructor and then stored in the this.itemIndex property.  So whenever you need to pass some extra parameters to a scene you do so just like we did here.  In the setup method we first instantiate and initialize the cookie model that we created earlier in this tutorial and then we get the contents of the list from the cookie and store it in the this.listContents property.  Next we continue on to setup the attributes for our text field, the most interesting part about the model is the model property which is set to original.  This tells the text field attributes that it should keep updated based on the model property.  You will see in our txtFieldModel we have an original property is being set.  It might look a bit complex to you but it really is not.  All it is doing is taking our list contents, fetching the proper index and grabbing the title property from that indexed element.  As you recall we passed in the item index, it was solely for this purpose.  </p>
<p>After we setup the text field and button we bind the button listener to the save method and when that is called that's where the magic happens.  The first thing it does is take the value from the text field and store it in our listContents under the same index so that we change the value.  It calls the setListContents method of our Model, calls the storeCookie method to save it and then swaps the scene back to the cookie scene.  If you build and deploy your application to the emulator or device it should work just as we expect it to.  It should load the default list where you can tap on Cookie.  It should then show the list from our stored cookie.  Keep in mind that on the first run the values will be the Default 1, Default 2, Default 3 that we set in the WBCookie model.  If you tap on any of these items you should be taken to the altercookie scene where you can change the value.  Once you hit the save button you should be taken back to the cookie list.  At this point if you execute the swipe back gesture you should be taken to the main list.</p>
<p>This concludes Part 2 of the series.  In <a href="http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/">Part 3</a> we are going to take a look at our code and do some restructuring.  In Part 4 we will look at using the Depot as a storage mechanism for our lists.  If you have any questions or if I have failed to explain something clearly enough for you please feel free to ask for help in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mojo Lists (Part 1)</title>
		<link>http://www.webosboston.org/2009/09/13/mojo-lists-part-1/</link>
		<comments>http://www.webosboston.org/2009/09/13/mojo-lists-part-1/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 00:15:56 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mojo]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Lists]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=137</guid>
		<description><![CDATA[At the request of a reader this next tutorial will cover Mojo Lists however it will get quite long so I have decided to break it into smaller parts.
Part 1 (This section) will deal with setting up a static list.
Part 2 will show how to use a cookie as a data source.
Part 3 will be [...]]]></description>
			<content:encoded><![CDATA[<p>At the request of a reader this next tutorial will cover Mojo Lists however it will get quite long so I have decided to break it into smaller parts.</p>
<p>Part 1 (This section) will deal with setting up a static list.<br />
<a href="http://www.webosboston.org/2009/09/21/mojo-lists-using-a-cookie-as-a-data-source-part-2/">Part 2</a> will show how to use a cookie as a data source.<br />
<a href="http://www.webosboston.org/2009/10/03/mojo-lists-restructuring-our-code-part-3/">Part 3</a> will be some restructuring of the code<br />
<a href="http://www.webosboston.org/2009/10/11/mojo-lists-using-the-depot-as-a-data-source-part-4/">Part 4</a> will show how to use the depot as a data source.<br />
Part 5 will show how to use an Sqlite database as the source.<br />
Source Code will be posted for download after the series is complete.</p>
<p>On our main scene we are going to show a static list of items.  This means that we are going to use an array of elements which will never change over the lifetime of the application.  The list item data will be specified by us and not fetched from any data source.  The main list will give you options to choose from such as using a Cookie, Depot or Sqlite for the data source.  When you tap on one of these options another scene will be displayed that will actually load another list.  The data that populates these lists will come from the data source that you specified.  This should give you the ability to write your own lists using any data source that you see fit.</p>
<p>The very first thing that you need to do is create a new WebOS application and add a new scene to it called main.  Now that we have the main scene created we need to alter our stage-controller.js so that it actually pushes the main-scene on startup.  Open the file and make the code look like this.</p>
<pre name="code" class="javascript">
function StageAssistant() {
}

StageAssistant.prototype.setup = function() {
    Mojo.Controller.stageController.pushScene("main");
}
</pre>
<p><span id="more-137"></span><br />
With that in place it's time to actually start working on the view file.  Let's open the main-scene.html file and add the following code to it.</p>
<pre name="code" class="html">
&lt;div id=&quot;feedTitle&quot; class=&quot;palm-header center&quot;&gt; List Data Sources
&lt;/div&gt; &lt;div class=&quot;palm-header-spacer&quot;&gt;&lt;/div&gt; &lt;div id=&quot;mainScene&quot; class=&quot;mainScene&quot;&gt;
&lt;div x-mojo-element=&quot;List&quot; id=&quot;mainListWgt&quot; &gt;&lt;/div&gt; &lt;/div&gt;
</pre>
<p>This is pretty basic HTML for the most part.  The only item that is really of concern here is the div that specifies the x-mojo-element=&quot;List&quot;.  This tells the Mojo Framework that you wish to have a list reside in that position in the view.  Now that we have the view in place and Mojo knows where we want our list to display it's time to actually start working on our list.  We will first need to create 2 template files.  We will put these files in the same directory as the main-scene.html file.  We will need one template for our list and then another template for each row in our list.  We will start off with the List template so create a file called mainListTemplate.html and add the following code to it.</p>
<pre name="code" class="html">
&lt;div class=&quot;palm-list&quot;&gt;#{-listElements}&lt;/div&gt;
</pre>
<p>All this file really does is create a div for our listElements to be placed in.  Think of a listElement as a row in the list.  You will notice one thing above that might look a little out of place and that is the use of the - (dash) in the template code.  Since each of our rows will contain HTML we need a way to tell Mojo not to escape this HTML so that our list will render properly.  Whenever you are using a value in a template with #{value} Mojo will escape the HTML and things will not look good.  If you add the dash as in #{-value} this specifically tells Mojo that we do not want the HTML escaped.</p>
<p>Let's continue on and create the list row template.  Create another file called mainRowTemplate.html.  Add the following contents.</p>
<pre name="code" class="html">
&lt;div class=&quot;palm-row&quot; x-mojo-touch-feedback=&quot;delayed&quot;&gt;
    &lt;div class=&quot;palm-row-wrapper&quot;&gt;
        &lt;div id=&quot;itemTitle&quot; class=&quot;title truncating-text&quot;&gt;#{title}&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>This file has a little bit more code than the last but it is all trivial.  First we create a div and use the class palm-row which is a CSS class defined in the Mojo Framework.  We are just applying some Palm default styling here.  You will also see the x-mojo-touch-feedback=&quot;delayed&quot;.  This tells the framework to have a short delay when a user taps on the item.  You can see this once you have everything setup and test the list.  We continue on to create another div and assign it the palm-row-wrapper class.  This is just a wrapper div that takes care of the look of the list row.  Inside that div is the actual div that you want to be concerned with.  You can notice that we are using the truncating-text class for this element.  All this does is truncate the text if it is too long to fit on the screen.  Rather than seeing the list look bad if the text is too long the style will truncate it at that perfect length as to not disturb how the list looks.  You might also notice that we are using #{title}.  You might wonder why we are not telling the framework to escape the HTML of the title however we do not want someone to inadvertently add HTML markup to the title and be able to change how things look in our list.  Letting Mojo escape the HTML will not add any formatting that we did not intend to have in place.</p>
<p>We are almost completed with our static list.  The last thing we need to do is actually put the JavaScript code in our assistant so that our list becomes something we can interact with.  We are going to open up the main-assistant file and make it look like the code below.</p>
<pre name="code" class="javascript">
function MainAssistant() {
        this.listItems = [
            {
                title: "Cookie"
            },
            {
                title: "Depot"
            },
            {
                title: "SqLite"
            }
        ];
}

MainAssistant.prototype.setup = function() {
    this.controller.setupWidget("mainListWgt",
        {
            itemTemplate: "main/mainRowTemplate",
            listTemplate: "main/mainListTemplate",
            swipeToDelete: false,
            renderLimit: 40,
            reorderable: false
        },
        {
            items: this.listItems
        }
    );

    this.mainListHandler = this.loadDataSource.bindAsEventListener(this);
    this.controller.listen("mainListWgt", Mojo.Event.listTap, this.mainListHandler);
}

MainAssistant.prototype.loadDataSource = function(event)
{
    Mojo.Controller.stageController.pushScene( this.listItems[event.index].title.toLowerCase() );
}

MainAssistant.prototype.activate = function(event) {

}

MainAssistant.prototype.deactivate = function(event) {

}

MainAssistant.prototype.cleanup = function(event) {

}
</pre>
<p>If you were to build your application right now it would load up the main scene and show you the static list.  It is not very pretty it is just a list that gives you the ability to choose a storage mechanism.  You can see in the MainAssistant() constructor I am initializing a variable called this.listItems which is an array that holds objects.  The objects are really basic as they only contain a title property however you could put any information in there.  If for instance you wanted a short description below the title of the list element you could add a description: "this is a brief description" to the objects and then put the code in place on the view for it to be displayed.  The objects are really just being used as a static storage mechanism for this main list.  When you look into the setup method you are going to see a few things that might seem foreign to you.  First you will sett a call to this.controller.setupWidget()  This is a method that we call which will actually set-up our list widget for use.  You have to pass in 3 parameters to this method.  First the ID of the element in the view, second the attributes which describe our widget.  For instance you will notice that we had to specify the list templates here.  The last item you have to provide is the model and that is the data that will populate the widget.</p>
<p>The last two lines of code you see in the setup method are the lines that actually set-up listening for the event handler.  The first line does the actual binding and sets that to a property of the MainAssistant.  The second line makes the call to the controller to setup the listener for the event we want.  We want something to be done when a user taps a list item so we are using the Mojo.Event.listTap event.  This method is very much like the setupWidget method as it also takes 3 arguments.  First the ID of the element in the HTML view file then the event we wish to listen for.  Finally you specify your method that you want called when the event is captured.  In our case we are going to call the method loadDataSource every-time a list item is tapped.</p>
<p>When the loadDataSource method is called the tap event is passed into it.  This is useful for finding out which list item was tapped.  We are using an array remember so when you tap an item the element index is passed into our method.  We simply reference the scene that we want pushed with the this.listItems[event.index].title.toLowerCase().  This is just fetching the proper item and converting the title to lowercase.  We need to call our scene by lowercase.  If you were to tap the Cookie item in the list then this code pushes the scene to cookie-scene.</p>
<p>There are just a few more things we need to do.  If you recall back in the setup method of the main-assistant we created a listener.  Now we need to clean up after that listener.  When the application is closed we want to stop listening for events.  If you do not clean up after your listeners your application will end up having memory leaks.  Luckily it is very easy to clean up after yourself.  Go back to your main-assistant file and add the following code to your cleanup method.</p>
<pre name="code" class="javascript">
MainAssistant.prototype.cleanup = function(event)
{
   Mojo.Event.stopListening(this.controller.get("mainListWgt"), Mojo.Event.listTap, this.mainListHandler);
}
</pre>
<p>The final bit that we need to do before we complete Part 1 is actually create the other scenes that we will need for each storage mechanism.  Create 3 more scenes named cookie, depot and sqlite.  Once you have done that you can feel free to build the application and test it out.  Tapping on a list item will show the default template.  In part 2 we will work on the ability to use a cookie as a storage mechanism.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/09/13/mojo-lists-part-1/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Working with Cookies</title>
		<link>http://www.webosboston.org/2009/08/28/working-with-cookies/</link>
		<comments>http://www.webosboston.org/2009/08/28/working-with-cookies/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 12:48:30 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mojo]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Cookie]]></category>
		<category><![CDATA[Storage]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[WebOS]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=78</guid>
		<description><![CDATA[Over the last few days I have been working with the Cookie as a method for storage on the Palm Pre.  I looked in the WebOS Book and there was a nice cookie class that could be used.  This will not be a complete walk-through like the last tutorials have been.  This [...]]]></description>
			<content:encoded><![CDATA[<p>Over the last few days I have been working with the Cookie as a method for storage on the Palm Pre.  I looked in the WebOS Book and there was a nice cookie class that could be used.  This will not be a complete walk-through like the last tutorials have been.  This will show you how to create a cookie object and how to interact with it so that you can store your application preferences.  You can store any type of data you would like in a cookie.  It does not seem to be like the Depot where you can *only* store objects.</p>
<p>At the time of writing I have found an issue with using cookies so be sure to read the second to last paragraph.<br />
Below is the class that was taken from the WebOS Book which we will be using for our Cookie object.</p>
<p><span id="more-78"></span></p>
<pre name="code" class="javascript">
// Globals
WBPrefs = {};
WBPrefs.someOtherValue = false;
WBPrefs.versionString = "0.0.1";

function WBCookie()
{

}

WBCookie.prototype.initialize = function()
{
    this.cookie = new Mojo.Model.Cookie('cookie_name');
    this.oldPrefs = this.cookie.get();
    if(this.oldPrefs)
    {
        // If current version, just update globals &#038; prefs
        if(this.oldPrefs.versionString == WBPrefs.versionString)
        {
            WBPrefs.someOtherValue = this.oldPrefs.someOtherValue;
            WBPrefs.versionString = this.oldPrefs.versionString;
        }
        else
        {
            // migrate old preferences here on updates of FreshBooks App.
        }
    }

    this.storeCookie();
};

WBCookie.prototype.storeCookie = function()
{
    this.cookie.put(
        {
            someOtherValue: WBPrefs.someOtherValue,
            versionString: WBPrefs.versionString
        }
    );
};
</pre>
<p>This code is pretty straight forward.  It creates a WBCookie object which actually interacts with the Mojo.Model.Cookie object.  You can see the initialize command does a few things.  First it creates a new Mojo.Model.Cookie object with the name of your cookie and stores it in a property named this.cookie.  It creates another property called this.oldPrefs which will store the values that are pulled out of the cookie.  It is called oldPrefs because they are the values that were last used for the application.  It then makes sure that oldPrefs is a valid object.  Once it knows we have a valid result we can then compare the versionString stored in the cookie with our application cookie versionString.  This allows us to properly migrate preferences if we ever change the structure of the cookie.  It then calls the this.storeCookie method which saves the current application Preferences into the cookie.  When you are using this method the cookie is updated everytime you update one of the WBPrefs values.  I am not entirely sure what causes it to update with every preference change it must be some magic done by the framework.</p>
<p>Now that we have the cookie class we will need to create a scene assistant which will make use of the cookie.  We will very simply create a view with a text field and a button.  You will be able to change the value in the textbox and tap the button to update the cookie value.  We will start with the following code.</p>
<pre name="code" class="javascript">
function FirstuseAssistant() {

}

FirstAssistant.prototype.setup = function() {
    this.cookie = new WBCookie();
    this.cookie.initialize();

    WBPrefs.someOtherValue = "Joseph Crawford";
}

FirstAssistant.prototype.activate = function(event) {

}

FirstAssistant.prototype.deactivate = function(event) {
        this.cookie.storeCookie();
}

FirstAssistant.prototype.cleanup = function(event) {

}
</pre>
<p>In the assistant code above you can see that we simply update the value of WBPrefs.someOtherValue which updates the cookie.  Next time we run the application the value will have been retained for our use again.  This comes in very handy for detecting which scene you should show.  For instance if your application will require a user to login you can check the cookie for the username / password and if they do not exist then show the sign-in scene otherwise show your main scene.</p>
<p>I am not sure what is happening whether palm has a bug in their code or if it is just my setup however when testing this all out I noticed that my cookies are retained on the emulator.  I have deleted the application from the emulator by holding the option key while tapping and I have also used the Komodo Add-On.  However my cookie seems to be retained across application installs and it should not be.  According to Palm's Documentation the cookies and databases related to an application should be removed from the device when the application is removed.  I personally have not tried it on the device but others have confirmed they have had their cookies be retained on the device as well.  Until this issue is fixed I really do not see a real use for cookies.  The data should not be retained across application installs.  Have you ever had the issue of a cookie being retained like this?  The only way I have found to test to make sure it was all working is to add a this.cookie.remove() before we set the cookie.  This will make the app remove the cookie whenever it is launched.  Obviously that is not production worthy code because the application settings would be removed on every launch.  It did however show me that my cookie was being retained and that my other code was working properly.</p>
<p>The code above is not a full example it just illustrates how to use the cookie model in Mojo.  You will have to do some of your own coding using these methods in order to use it properly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/08/28/working-with-cookies/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tutorial Suggestions&#8230;</title>
		<link>http://www.webosboston.org/2009/08/18/tutorial-suggestions/</link>
		<comments>http://www.webosboston.org/2009/08/18/tutorial-suggestions/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 23:40:49 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[WebOS]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=36</guid>
		<description><![CDATA[What would you guys like to see in the next tutorial?  I am open to ideas.  I want to be able to teach people the correct methods for WebOS Development and do not want to start writing stuff if people are not going to find it beneficial.
]]></description>
			<content:encoded><![CDATA[<p>What would you guys like to see in the next tutorial?  I am open to ideas.  I want to be able to teach people the correct methods for WebOS Development and do not want to start writing stuff if people are not going to find it beneficial.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/08/18/tutorial-suggestions/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A Basic WebOS Application and the Depot</title>
		<link>http://www.webosboston.org/2009/08/17/a-basic-webos-application-and-the-depot/</link>
		<comments>http://www.webosboston.org/2009/08/17/a-basic-webos-application-and-the-depot/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 11:02:26 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Depot]]></category>
		<category><![CDATA[Mojo]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[WebOS]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=13</guid>
		<description><![CDATA[A lot of people are trying to understand how to write applications for WebOS so I figured the very first tutorial I would create for this site would be a simple walk-through of creating a very basic application.  I am going to go a bit deeper than just a basic application like they cover [...]]]></description>
			<content:encoded><![CDATA[<p>A lot of people are trying to understand how to write applications for WebOS so I figured the very first tutorial I would create for this site would be a simple walk-through of creating a very basic application.  I am going to go a bit deeper than just a basic application like they cover in the Hello World example.  The application created in this walk-through will explain the concepts behind creating a basic application, explaining what each part is and why you have to do it that way.  I will also introduce the Depot in this walk-through.  Are you ready?</p>
<p><strong>The Tools I Use</strong><br />
Everyone will have their own set of tools that they use and they do not have to be the same as mine, however please note that I am not going to give the terminal commands for pushing the app to the emulator etc.  My tools do that all for me and allow me to focus on developing my application.  </p>
<p>The very first thing you should install is the Palm Developer SDK which you can get from the <a href="http://developer.palm.com/">Palm Developer Website</a>.  For my Editor I use <a href="http://www.activestate.com/komodo/">Komodo IDE</a> with the very nice add-on that Templarian has created.  If you do not have a license for Komodo IDE you can use the free version of <a href="http://www.activestate.com/komodo_edit/">Komodo Edit</a>.  You can download the add-on on <a href="http://webos.templarian.com/komodo-alpha/">Templarian's website</a> and installing is as easy as dragging and dropping on your editor window.  The last thing I use is a file that you import into your editor that provides code completion for your editor.  You can download this file <a href="http://webos.templarian.com/komodo/">here</a>.  Please note that you want to click the Download link and download the rawmojo.zip file.  Installation instructions can be found on the same page.  You can ignore the tool-kit as the tool-kit is the ancestor of the add-on.</p>
<p>Once you have these things installed you are all ready to start developing your first WebOS application.</p>
<p><span id="more-13"></span><br />
<strong>Building the Application</strong><br />
Fire up your editor and make sure the WebOS add-on is seen on your screen, if it is not then click on the View menu and at the very bottom click on WebOS.  This will open the WebOS panel that will give you access to everything you need while developing WebOS applications.  Since this tutorial is about creating an application I am not going to cover every feature of the Komodo WebOS add-on.  Below is a screen shot of the WebOS add-on window.  I will explain what you need to do using this image as a basis so be sure to reference this image if necessary.</p>
<p><a href="http://www.webosboston.org/wp-content/uploads/2009/08/main_window.png" target="_blank"><img src="http://www.webosboston.org/wp-content/uploads/2009/08/main_window.png" alt="Main Window" title="Main Window" width="468" height="105" class="floatcenter" /></a></p>
<p>The first thing you need to do is click the icon in the top left corner and choose New Project.  Fill out the text boxes in the screen that follows.  Make sure you fill everything in and select the path for the application by clicking on the icon to the right of the path field.  Once you have created the project the add-on will create the directory structure and put the project in the Projects explorer which is located on the left side of the screen.  If you do not see it try clicking on the View menu and select Tabs &#038; Sidebars and make sure projects is checked.</p>
<p>Now that we have the project all setup it is time to actually start coding the application.  I am not going to cover the directory structure in this tutorial, you can learn about all of that at the <a href="http://developer.palm.com/">Palm Developer Website</a>.  The very first thing that we need to do is to create our first scene.  We are going to name this scene 'main' so click on the same icon you did to create the project but this time click on New Scene.  After you click on New Scene a text box will appear type the word 'main' without the quotes into that box and click the icon immediately to the right of the text box.  This has now created the scene for you.  It has put the scene html file in place as well as the scene assistant and has also modified your sources.json so that the application will be able to find this scene.</p>
<p>Now that we have the main scene we are going to alter the html that is in the file found in app/views/main/main-scene.html.  You can go ahead and delete any text that is currently in that file because it is auto generated by the SDK.  Below is the source code for the main-scene.html file.</p>
<pre name="code" class="html">
    &lt;div id="main" class="palm-hasheader"&gt;
        &lt;div class="palm-header"&gt;WebOS Boston&lt;/div&gt;
        &lt;div id="addBtn" name="addBtn1" x-mojo-element="Button"&gt;&lt;/div&gt;
        &lt;div id="getBtn" name="getBtn1" x-mojo-element="Button"&gt;&lt;/div&gt;
    &lt;/div&gt;
</pre>
<p>You will notice a few things in the HTML code above one the fact that I am using a palm-hasheader css class.  This comes from the Mojo framework and is not defined in my sources.  Next you will notice that I define 2 div elements that have a strange attribute called x-mojo-element.  This tells the framework that you want to use a widget and to have it display in this spot.  I have defined two buttons, one for showing a scene where you can add a value to the depot and the other shows the scene where you can get the value.  Now that we have this in place it is time to actually write the code for the assistant.  Below is the code I created for the assistant.</p>
<pre name="code" class="javascript">
function MainAssistant() {

}

MainAssistant.prototype.setup = function() {
  // Setup our Add Value Button and Event Handler
  this.addBtnAttributes = {};

  this.addBtnModel = {
    buttonLabel : 'Add Value',
    buttonClass : '',
    disabled : false
  };

  this.controller.setupWidget(
    "addBtn",
    this.addBtnAttributes,
    this.addBtnModel
  );

  Mojo.Event.listen(
    this.controller.get('addBtn'),
    Mojo.Event.tap,
    this.showAddValueScene.bind(this)
  );

  // Setup our Get Value Button and Event Handler
  this.getBtnAttributes = {};

  this.getBtnModel = {
    buttonLabel : 'Get Value',
    buttonClass : '',
    disabled : false
  };

  this.controller.setupWidget(
    "getBtn",
    this.addBtnAttributes,
    this.getBtnModel
  );

  Mojo.Event.listen(
    this.controller.get('getBtn'),
    Mojo.Event.tap,
    this.showGetValueScene.bind(this)
  );
}

MainAssistant.prototype.showAddValueScene = function()
{
  this.controller.stageController.pushScene('add');
}

MainAssistant.prototype.showGetValueScene = function()
{
  this.controller.stageController.pushScene('get');
}

MainAssistant.prototype.activate = function(event) {

}

MainAssistant.prototype.deactivate = function(event) {

}

MainAssistant.prototype.cleanup = function(event) {
    this.controller.stopListening(this.controller.get('getBtn'), Mojo.Event.tap, this.showGetValueScene);
    this.controller.stopListening(this.controller.get('addBtn'), Mojo.Event.tap, this.showAddValueScene);
}
</pre>
<p>I am going to start by describing what these methods are and when they are called.  The constructor function is the first thing called when this scene is run.  We are not doing anything in the constructor function however we could have set some class properties etc if any parameters were passed into the object.  The set-up method is called next in our case when this scene is created.  The other methods activate and deactivate are called when your application is pushed to the background or pulled back to the foreground.  The final method named cleanup is called when the application is closed and this is where we are going to remove our event handlers.  If you fail to remove any event handlers that you setup with the listen method you will find that your application will probably leak memory.  The setup method is where I am setting up our buttons and event handlers for the scene to render.  You will notice that each button has an attributes object and a model object.  You can learn what parameters can be specified by looking at the palm documentation for the <a href="http://developer.palm.com/palm-sdk/jsdoc/symbols/Mojo.Widget.html#.Button">Button Widget</a>.  You will notice that I am calling a method called setupWidget.  This is the method that will actually get the framework to setup the widget on your scene.  You *must* pass this function 3 parameters.</p>
<p>The first is the ID of the widget in the HTML scene.  The second is the attributes object followed by the model object.  Once you have this in place your button should show on your scene, however you will want to do something when a user taps your button.  We need to set-up the event listener and you can see that on the line following the setupWidget function call.  In order to set-up an event listener we need to pass the method 3 things.  The actual widget element which is handled with the this.controller.get method call.  We also need to pass it the type of event we wish to respond to.  In this case we want to respond to Mojo.Event.tap events.  The last item is a callback function, when the event takes place you tell it that you want this method executed.  You can see in the assistant method for showAddValueScene and showGetValueScene I am just making a call to this.controller.stageController.pushScene().  This is basically just saying I want to get the applications stage controller from this assistants controller and I want to tell the stageController to push a different scene.</p>
<p>Now that we have that code in place we need to tell the stage-assistant that we want it to push our newly created scene when the application starts.  To do this all we have to do is add one line of code to the stage-assistant.  You can see the source code below.</p>
<pre name="code" class="javascript">
function StageAssistant() {

}

StageAssistant.prototype.setup = function() {
  this.controller.pushScene('main');
}
</pre>
<p>Since we have that in place we need to create our next 2 scenes.  As you recall in the main-assistant.js file we created the two methods that we are using for the event handlers for the buttons we created.  In those methods we got an instance of the stage-controller and told it to push a scene.  Now is the time to create both of those scenes.  In the WebOS add-on click the same icon you did earlier and create 2 more scenes.  Name these scenes add and get.  Once you have done that make sure your emulator is open and running.</p>
<p>Now that we have prepared the basics of our application we are going to run it in the emulator.  Click the button in the WebOS addon that looks like a brown box with the green circular plus sign on it.  This will package your application, install it to the emulator and launch it.  When the application launches you should see the two buttons that you created.  Go ahead a click on one of the buttons.  Notice it changes the scene to show the newly created scenes.  They do not show anything significant as we left the stock scene templates in place.  That will change soon don't worry.</p>
<p>With all of that out of the way I want to explain a bit about what the Depot is exactly and why you would want to use it.  When dealing with storage on the WebOS Device you have three options to choose from.  You can use a Cookie, Depot or an Sqlite database.  One question many people have is when should I use one over the other?  If you are just storing preferences for your application or some other small bits of data I would suggest you use a cookie.  However if you find that you want to store quite a bit of data then you have another choice to make.  Should you use a Depot or an Sqlite database?  Well it all depends on how much data you are storing and it will depend on where you store your depot database.  If you just use the default depot storage location you are limited to 1 MB for the database because this is stored in a spot on your device which is limited in space.  It will also depend on whether or not you want to use a structured database, if so you should use the HTML5 Database (Sqlite).  You can opt to specify that the database be stored as EXT which will store it on the media partition of the device and you are then only limited by the space which the user has on the device.  In order to specify that a database be stored on the media partition you just have to prefix the name of the database with ext: so for instance you would do something like the following.  Don't worry if you do not understand this code you will see it again shortly I just wanted to show it so that you could see how to store a database on the media partition of the device.  One important thing to mention is what had been tripping me up all week while messing with the depot.  For some reason it only likes to store objects and not any other type of value.  For instance you cannot set var value = true; and try to set that with the depot.  You have to do { "value" : true } and store that object into the depot.  I do not recall getting any errors from the depot it just would not retrieve my stored value.</p>
<pre name="code" class="javascript">
  var options = {
	name: "ext:webosboston_basic_tutorial", //Name used for the HTML5 database name. (required)
	version: 1, //Version number used for the HTML5 database. (optional, defaults to 1)
	replace: false // open an existing depot
  };
</pre>
<p>So now that we know the different types of storage for developers on WebOS we will need to go over what the depot actually does.  I have been fiddling with the Depot for about a week now and I have gone over the source code for the Depot which is included in the SDK.  The Depot is basically an abstraction layer to the Sqlite database.  It uses Sqlite in the background but gives you an API to use rather than having to know how to write proper SQL statements.  You first need to open or create the database which is done by the SDK when you tell it to.</p>
<p>Now we are going to work on our Depot connection so go back into the main-assistant.js file and make it look like the code below.</p>
<pre name="code" class="javascript">
function MainAssistant() {
  var options = {
	name: "webosboston_basic_tutorial", //Name used for the HTML5 database name. (required)
	version: 1, //Version number used for the HTML5 database. (optional, defaults to 1)
	replace: false // open an existing depot
  };

  //Create a database when the scene is generated
  this.depot = new Mojo.Depot(options, this.dbConnectionSuccess, this.dbConnectionFailure);
}

MainAssistant.prototype.setup = function() {
  // Setup our Add Value Button and Event Handler
  this.addBtnAttributes = {};

  this.addBtnModel = {
    buttonLabel : 'Add Value',
    buttonClass : '',
    disabled : false
  };

  this.controller.setupWidget(
    "addBtn",
    this.addBtnAttributes,
    this.addBtnModel
  );

  Mojo.Event.listen(
    this.controller.get('addBtn'),
    Mojo.Event.tap,
    this.showAddValueScene.bind(this)
  );

  // Setup our Get Value Button and Event Handler
  this.getBtnAttributes = {};

  this.getBtnModel = {
    buttonLabel : 'Get Value',
    buttonClass : '',
    disabled : false
  };

  this.controller.setupWidget(
    "getBtn",
    this.addBtnAttributes,
    this.getBtnModel
  );

  Mojo.Event.listen(
    this.controller.get('getBtn'),
    Mojo.Event.tap,
    this.showGetValueScene.bind(this)
  );
}

MainAssistant.prototype.showAddValueScene = function()
{
  this.controller.stageController.pushScene('add', this.depot);
}

MainAssistant.prototype.showGetValueScene = function()
{
  this.controller.stageController.pushScene('get', this.depot);
}

MainAssistant.prototype.activate = function(event) {

}

MainAssistant.prototype.deactivate = function(event) {

}

MainAssistant.prototype.cleanup = function(event) {
    this.controller.stopListening(this.controller.get('getBtn'), Mojo.Event.tap, this.showGetValueScene);
    this.controller.stopListening(this.controller.get('addBtn'), Mojo.Event.tap, this.showAddValueScene);
}
</pre>
<p>Improvements: In the constructor we create an options object to store some configuration values for the database.  We are telling the framework to create or open the database for the name we specified and also telling it to use a few methods as a callback for the database connection.  When you create/open a connection the framework will call back to a success or failure function that you specify so that you can handle any errors.</p>
<p>We're passing this.dbConnectionSuccess and this.dbConnectionFailure however we never define them in the main-assistant.js class file.  This is because they will not be called on this object.  They will be called from the scene assistant that we are doing the database work from, we will create this code shortly.  One last thing I want to make clear to all of you is in the add and get callback methods we created to push the scenes when a button is clicked we have added this.depot to the call.  This is perfectly valid.  In-fact you can put as many parameters as you want in the pushScene() method.  After it knows the scene name any additional parameters will be passed to that scene assistant for processing internally.</p>
<p>We will first start with the add-scene and the scene assistant.  We will need to have two text boxes and a button on this scene along with a hidden element which will display any errors or success messages when we store the value into the database.  So let's get started.  Open up the add-scene.html and make it have the same code as I have in mine below.</p>
<pre name="code" class="html">
&lt;div id=&quot;main&quot; class=&quot;palm-hasheader&quot;&gt;
  &lt;div class=&quot;palm-header left&quot; id=&quot;list-header&quot;&gt;
    Add / replace data
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;palm-group&quot;&gt;
  &lt;div class=&quot;palm-group-title&quot;&gt;&lt;span x-mojo-loc=&quot;&quot;&gt;Database Info.&lt;/span&gt;&lt;/div&gt;
    &lt;div class=&quot;palm-list&quot;&gt;
      &lt;div class='palm-row first'&gt;
        &lt;div class=&quot;palm-row-wrapper textfield-group&quot; x-mojo-focus-highlight=&quot;true&quot;&gt;
          &lt;div class=&quot;title&quot;&gt;
            &lt;div class=&quot;label&quot;&gt;Key&lt;/div&gt;
            &lt;div id=&quot;keyField&quot; name=&quot;keyField&quot; x-mojo-element=&quot;TextField&quot; &gt;&lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class='palm-row last'&gt;
        &lt;div class=&quot;palm-row-wrapper textfield-group&quot; x-mojo-focus-highlight=&quot;true&quot;&gt;
          &lt;div class=&quot;title&quot;&gt;
            &lt;div class=&quot;label&quot;&gt;Text&lt;/div&gt;
            &lt;div id=&quot;textField&quot; name=&quot;textField&quot; x-mojo-element=&quot;TextField&quot; &gt;&lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;depotResult&quot; class=&quot;info-text&quot;&gt;&lt;/div&gt;

&lt;div class=&quot;palm-button&quot; id=&quot;add_button&quot;&gt;Add entry&lt;/div&gt;
&lt;div class=&quot;palm-button&quot; id=&quot;back_button&quot;&gt;Back to main view&lt;/div&gt;
</pre>
<p>The first thing I want to point out is how we are using the palm-group css style.  This is how you will group controls together so that they look uniform and not out of place.  When we get to the point of running the application you will see what it makes it look like.  For now just understand that we are grouping items together.  You will also see a reference to x-mojo-focus-highlight="true" in the code above.  This tells the framework that we want this item to have focus when the scene is loaded.  Since we are telling it to give focus to a text field the cursor will be in that field whenever we load that particular scene.  Now that we have the HTML out of the way it's time to actually work on the code that will make the application work.  We are going to alter the add-assistant.js code to give this scene the functionality that we require.</p>
<pre name="code" class="javascript">
function AddAssistant(arg){
	this.depot = arg;
}

AddAssistant.prototype.setup = function() {

	//Create the attributes for the textfield
	this.keyFieldAtt = {
			hintText: 		'Enter key here',
			modelProperty:	'originalValue',
                        textCase:       Mojo.Widget.steModeLowerCase,
			focus:			true,
			maxLength: 		30
	};
	//Create the model for the text field
	this.keyModel = {
		originalValue : ''
	};

	this.textFieldAtt = {
		hintText: 		'and some text here',
		modelProperty:	'originalValue',
                textCase:       Mojo.Widget.steModeLowerCase,
		multiline:		false,
		focus: 			false,
		maxLength: 		30
	};
	this.textModel = {
		originalValue : ''
	};

	//Setup the textfield widget and observer

	this.controller.setupWidget('keyField', this.keyFieldAtt, this.keyModel);
	this.controller.setupWidget('textField', this.textFieldAtt, this.textModel);

	Mojo.Event.listen(this.controller.get('add_button'),Mojo.Event.tap, this.add.bind(this));
	Mojo.Event.listen(this.controller.get('back_button'), Mojo.Event.tap, this.back.bind(this));

	this.depotResult = this.controller.get("depotResult");
}

AddAssistant.prototype.add = function(){
	Mojo.Log.info("%s : %s", this.keyModel.originalValue, this.textModel.originalValue);

	this.data = { "val" :this.textModel.originalValue };

	this.depot.simpleAdd(this.keyModel.originalValue, this.data, this.dbSuccess, this.dbFailure);
}

AddAssistant.prototype.back = function(){
	Mojo.Controller.stageController.popScene();
}

AddAssistant.prototype.dbSuccess = function() {
	Mojo.Log.info("***** depot operation success!");
	this.depotResult.innerHTML = ("Add success!");
}

AddAssistant.prototype.dbFailure = function(transaction, result) {
	Mojo.Log.info("***** depot failure: %s", result.message);
	this.depotResult.innerHTML = ("Add failure!");
}

AddAssistant.prototype.cleanup = function()
{
        /* Cleanup our listeners so there is no memory leak. */
        this.controller.stopListening(this.controller.get('add_button'), Mojo.Event.tap, this.add);
        this.controller.stopListening(this.controller.get('back_button'), Mojo.Event.tap, this.back);
}
</pre>
<p>In this assistant, Mojo.Log.info() is a logging class, it logs messages to the /var/log/messages file on the emulator or the device.  This allows you to see the progress the app is making when running and any errors should you have any.  If you are not familiar with how it works you should read up on the <a href="http://developer.palm.com/palm-sdk/jsdoc/symbols/Mojo.Log.html">Mojo.Log.* methods</a>.  The next thing you will notice is that each of our text fields have properties set in the attributes and model objects.  Most of these are self-explanatory but I will say that the modelProperty property in the attributes object tells the widget what field to look for in the model for the value of the field.  You will also notice the addition of a cleanup method.  This is the method that is called when the scene is destroyed and you should use it to clean up any event listeners that you have created.  If you do not clean up after your event listeners they are just going to be hanging around eating up the memory on the device.  You will also notice that in the attribues object we are calling a Mojo.Widget object to get the textCase.  There are other ways that you can do this however this is the standard the other methods have been depreciated.  All this method call does is set the case for the text in the text field.  We are just turning off the auto capitalization so that when you type the first letter is not capitalized.  We will be using this throughout the project.  The one last thing that is different is how the depot is passed into this scene.  In the constructor you can see that arg is passed in and then we are calling this.depot = arg;  This allows us to have access to the depot for adding the values.</p>
<p>The next part is the get scene where we will be able to look-up values for the keys we have set using the add scene.  On the get scene all we will need is to have one text field and a button.  We will enter our depot key into the text field and when you tap the button it will fetch the value from the depot and update an element on the page.  Below is the HTML code we are going to use for our view file.</p>
<pre name="code" class="html">
&lt;div id=&quot;main&quot; class=&quot;palm-hasheader&quot;&gt;
  &lt;div class=&quot;palm-header left&quot; id=&quot;list-header&quot;&gt;
	Depot Sample
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;info-text&quot;&gt;Which data entry you want to get?&lt;/div&gt;

&lt;div class=&quot;palm-group&quot;&gt;
&lt;div class=&quot;palm-group-title&quot;&gt;Enter key string&lt;/div&gt;
  &lt;div class=&quot;palm-list&quot;&gt;
	&lt;div class=&quot;palm-row single&quot;&gt;
	  &lt;div class=&quot;palm-row-wrapper textfield-group&quot; x-mojo-focus-highlight=&quot;true&quot;&gt;
		&lt;div class=&quot;title&quot;&gt;
		  &lt;div id=&quot;entryNum&quot; x-mojo-element=&quot;TextField&quot; &gt;&lt;/div&gt;
		&lt;/div&gt;
	  &lt;/div&gt;
	&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div id=&quot;response&quot;&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;palm-button&quot; id=&quot;get_button&quot;&gt;Get Entry&lt;/div&gt;
&lt;div class=&quot;palm-button&quot; id=&quot;back_button&quot;&gt;Back to main view&lt;/div&gt;
</pre>
<p>There is not anything new in the code above we setup a single text field and 2 buttons.  One for calling the depot to get the value and the other for going back to the main scene.  The next step is to actually create the assistant javascript code so that we can capture events when buttons are tapped.</p>
<pre name="code" class="javascript">
function GetAssistant(arg){
	this.depot = arg;
}

GetAssistant.prototype.setup = function(){
	this.keyAtt = {
			hintText:       'Enter key here',
			modelProperty:	'originalValue',
                        textCase:       Mojo.Widget.steModeLowerCase,
			multiline:		false,
			focus: 			true,
			maxLength: 30
		};
		this.keyModel = {
			originalValue : ''
		};

		//Setup the textfield widget and observer

		this.controller.setupWidget('entryNum', this.keyAtt, this.keyModel);
		Mojo.Event.listen(this.controller.get('get_button'),Mojo.Event.tap, this.get.bindAsEventListener(this));
		Mojo.Event.listen(this.controller.get('back_button'),Mojo.Event.tap, this.back.bindAsEventListener(this));
}

GetAssistant.prototype.get = function(){

	this.depot.get(this.keyModel.originalValue, this.dbGetSuccess, this.dbFailure);
}

GetAssistant.prototype.back = function(){
	Mojo.Controller.stageController.popScene();
}

GetAssistant.prototype.dbGetSuccess = function(response){

	var recordSize = Object.values(response).size();
	if(recordSize == 0) {
		$('response').update("No such record in the database");
	} else {
		$('response').update("Data entry is: " + response.val);
	}
}

GetAssistant.prototype.dbFailure = function(transaction, result) {
	Mojo.Log.info("***** depot failure: %s", result.message);
}
</pre>
<p>There is one new part in the dbGetSuccess method.  The new part is the section where you will see recordSize = Object.values(response).size().  This is actually a feature of the prototype framework that will allow you to take an object and treat it as a hash.  All it really does it turn an object's properties into an array.  The size() method returns how many items are in the array so this is just checking to see if there is at-least 1 value returned from the depot.  If not it shows a nice message about not being able to find the item in the depot.  Once the item is found the element on the page is updated to show the value as the message.  Another part that is new is the way that it updates the element on the scene which shows the results of the depot calls.  You will notice the $('response').update("");  All this is doing is getting the response element from the scene and updating the value to be whatever the message is between the quotes.</p>
<p>At this point the project is completed, however we need to update the emulator with the latest version.  Since we launched last time the old version is still on the emulator.  You will need to click the icon in the WebOS panel that looks like a brown box with a - (minus sign) in a red circle.  It's the 3rd box icon from the left.  Once you have done that click the box icon with the plus sign in the green circle to install the new version to the emulator.  When the app launches you will be able to store and fetch values from the depot.</p>
<p>This has been a very basic introduction to creating an application with WebOS and using the Depot.  The depot has much more functionality which you can see by checking out the <a href="http://developer.palm.com/palm-sdk/jsdoc/symbols/Mojo.Depot.html">API documentation</a>.  Remember you can *only* store objects in a depot if you try to store any other type of value you are going to run into problems with your application.</p>
<p>The source code for this project can be <a href='http://www.webosboston.org/wp-content/uploads/2009/08/org.webosboston.basic.zip'>downloaded from here</a> so that you can follow along. Feel free to write the code yourself if you want to learn the most from this tutorial.</p>
<p>If you would like to write tutorials for us please <a href="http://www.webosboston.org/contact-us/">contact us</a> to let us know.  We would be more than happy to have more contributors on the team.</p>
<p><strong><em>Disclaimer: Portions of the code above were taken from the Data Sample application that Palm provides with the SDK.</em></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/08/17/a-basic-webos-application-and-the-depot/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Tutorials</title>
		<link>http://www.webosboston.org/2009/08/13/tutorials/</link>
		<comments>http://www.webosboston.org/2009/08/13/tutorials/#comments</comments>
		<pubDate>Fri, 14 Aug 2009 02:03:19 +0000</pubDate>
		<dc:creator>Joseph Crawford</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.webosboston.org/?p=10</guid>
		<description><![CDATA[I will be writing tutorials on creating applications for WebOS and posting them on this site.  If you would be interested in helping to write tutorials for the user group.  Please contact us to let us know by using the contact page.
]]></description>
			<content:encoded><![CDATA[<p>I will be writing tutorials on creating applications for WebOS and posting them on this site.  If you would be interested in helping to write tutorials for the user group.  Please contact us to let us know by using the <a href="http://www.webosboston.org/contact-us/">contact page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webosboston.org/2009/08/13/tutorials/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.650 seconds -->
