<?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; Mojo</title>
	<atom:link href="http://www.webosboston.org/category/mojo/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>
	</channel>
</rss>

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