tag:blogger.com,1999:blog-6199085291581463792024-03-19T00:26:20.310-07:00Tech DojoFrom Ideas to TechniquesUnknownnoreply@blogger.comBlogger10125tag:blogger.com,1999:blog-619908529158146379.post-25798958337180487272012-07-31T23:18:00.000-07:002012-08-07T00:00:21.172-07:00ZK in Action [4] : Styling and LayoutIn the previous ZK in Action posts we went through implementing a <a href="http://techdojo.blogspot.ca/2012/07/zk-in-action-3-mvvm-working-together.html" target="_blank">CRUD feature using ZK MVVM</a>. We also quickly went through some styling code that may deserve more explanation.<br />
<br />
In this post, we'll go over how to append new CSS styling rules onto ZK widgets and how to override the existing styling. We'll also introduce some basics of UI layout in ZK.<br />
<br />
<h3>Objective<br />
</h3><ul><li>Use ZK's layout and container widgets to host the inventory CRUD feature we built in the previous posts.<br />
</li>
<li>Style the ZK widgets </li>
</ul><br />
<h3>ZK Features in Action </h3><ul><li>Borderlayout</li>
<li>Hlayout</li>
<li>Tabbox</li>
<li>Include</li>
<li>sclass</li>
</ul><br />
<h3>Using Layouts and Containers</h3><h4>The Borderlayout and Hlayout</h4>The Borderlayout divides the window into 5 sections as shown below:<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcPvfetLgb77gdBRGo3G8otqRRDoBjhfRJZ9W7q4sQ5IEDqY4XdtZjNkmHe-g_TIhrp9f9mIGmLlfXA_3bqVWs-JNns-OMaayJY3esjfYKimGzCdH22fiiZLUbq4JrIDbQm7ZQ0lx6Ykg/s1600/borderlayout.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="308" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcPvfetLgb77gdBRGo3G8otqRRDoBjhfRJZ9W7q4sQ5IEDqY4XdtZjNkmHe-g_TIhrp9f9mIGmLlfXA_3bqVWs-JNns-OMaayJY3esjfYKimGzCdH22fiiZLUbq4JrIDbQm7ZQ0lx6Ykg/s640/borderlayout.png" width="640" /></a></div><br />
Without further ado let's dissect the markup and see how it works:<br />
<pre class="brush:html; highlight=[4];"><window ...">
<borderlayout width="100%" height="100%">
<north size="15%">
<hlayout width="100%" height="100%">
<label hflex="9" value="Alpha Dental" />
<label hflex="1" value="Sign Out" ></label>
</hlayout>
</north>
<east size="10%"></east>
<center>
<tabbox width="100%" height="100%" orient="vertical">
<tabs width="15%">
<tab label="Inventory" />
<tab label="TBD" />
<tab label="TBD"/>
</tabs>
<tabpanels>
<tabpanel>
<include src="inventory.zul"/>
</tabpanel>
<tabpanel></tabpanel>
<tabpanel></tabpanel>
</tabpanels>
</tabbox>
</center>
<west size="10%" ></west>
<south size="10%"></south>
</borderlayout>
</pre><ul><li>line 3 and 27, the north and south widgets can be adjusted for height but not width </li>
<li>line 9 and 26, the east and west widgets can be adjusted for width but not height</li>
<li>line 10, the center widget's dimensions are dependent on those entered for the north, west, south, and east widgets</li>
<li>from line 4 through 7, we wrap the two labels with an Hlayout so they'll be displayed side by side proportionally with respect to the "hflex" attribute we specified. That is, the Label assigned with hflex="9" has 9 times the width of the Label assigned with hflex="1".</li>
<li>each inner widget (north, west, etc.) can accept only a single child component, hence, multiple widgets must be wrapped by a single container widget such as Hlayout before placed inside the Borderlayout inner widgets (north, west, etc.)</li>
<li>line 11, we place a Tabbox element and set its orientation as vertical in anticipation of embedding <a href="http://techdojo.blogspot.ca/2012/07/zk-in-action-3-mvvm-working-together.html" target="_blank">our inventory CRUD feature</a> inside it</li>
<li>line 12 to 16, we put the heading for each tab</li>
<li>line 18, a Tabpanel is a container that holds a tab's content</li>
<li>line 19, we embed our inventory CRUD feature inside an Include tag. The widgets on inventory.zul will be attached to this page</li>
</ul><br />
<h4>Overriding the Existing ZK Styling Rules</h4>The ZK default font properties and the background colours were modified so headings would be presented more prominently. Let's quickly explain how this is accomplished.<br />
Using Chrome Developer Tool or the Firebug extension, we could easily inspect the source of our Borderlayout and find the ZK styling class for the ZK widgets as shown below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2GwwfST_8Aa3EAoHZRz1ZpBR7nEaRZctqraZoGV_mndFRV7X8cH4YfNGjlI-so0Dn7r2OYUWDsU05yOS8e8spAh8UGG79bBd_OoBQEe8O3XcnpuC5csr3KBIfwpSv3bfvMymbWgMA3U4/s1600/findzclass.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2GwwfST_8Aa3EAoHZRz1ZpBR7nEaRZctqraZoGV_mndFRV7X8cH4YfNGjlI-so0Dn7r2OYUWDsU05yOS8e8spAh8UGG79bBd_OoBQEe8O3XcnpuC5csr3KBIfwpSv3bfvMymbWgMA3U4/s1600/findzclass.png" /></a></div>From here we learned that the naming pattern for the highlighted region is z-north-body. Similarly, we could do the same for all the markup of interest and go ahead overriding their CSS styling rules:<br />
<pre class="brush:html; highlight=[4];"><zk>
<style>
.z-tab-ver .z-tab-ver-text { font-size: 18px; }
.z-north-body, .z-south-body { background:#A3D1F0 }
.z-east-body, .z-west-body { background:#F8F9FB }
</style>
<window border="none" width="100%" height="100%">
<borderlayout width="100%" height="100%">
<north size="15%">...</north>
<east size="10%"></east>
<center>...</center>
<west size="10%"></west>
<south size="10%"></south>
</borderlayout>
</window>
</zk>
</pre><br />
<h4>Appending Additional Styling Rules via Style Attribute</h4>Here we're modifying the styling of the Labels contained in the North widget. Since we only want these two Labels, not all of them, to be affected by our new styling, it does not make sense for us to override the original styling as we did before. For these isolated modifications, it suffice to simply assign the styling rules to the "style" attribute that comes with the ZK widgets:<br />
<pre class="brush:html; highlight=[4];"><north size="15%">
<hlayout width="100%" height="100%">
<label value="Alpha Dental" style="font-size: 32px; font-style: italic; font-weight:bold; color:white; margin-left:8px;"/>
<label value="Sign Out" style="font-size: 14px; font-weight:bold; color:grey; line-height:26px"></label>
</hlayout>
</north>...
</pre><br />
<h4>Appending Additional Styling Rules via Sclass</h4>An alternative to assign styling rules directly in the markup and pollute the code is to declare a styling class, abbreviated as "sclass", and assign the rules to the "sclass" attribute as shown here:<br />
<pre class="brush:html; highlight=[4];"><zk>
<style>
.company-heading {
font-size: 32px;
font-style: italic;
font-weight:bold;
color:white;
margin-left:8px;
}
</style>
<window ...>
<borderlayout ...>
<north ...> <label value="Alpha Dental" sclass="company-heading"/></north>
...
</borderlayout>
</window>
</zk>
</pre><br />
<h3>In a Nutshell</h3><ul><li>Three ways to modify the default ZK styling is covered in this post: override the existing ZK styling class, assign styling rules directly to a widget's <i><b>style</b></i> attribute, or define a CSS class in a CSS file or inside a <b>Style</b> tag then assign the class to the widget's <i><b>sclass</b></i> attribute</li>
<li>Use a developer tool(such as Firebug) to inspect the ZK widgets and find out which ZK style class to override</li>
<li>The hlex attribute allows developers to define widgets' width proportionally with respect to each other</li>
<li> Layout widgets help developers to divide the presentation window into sections </li>
</ul><br />
<h3>References</h3><a href="http://books.zkoss.org/wiki/ZK%20Style%20Guide">ZK Styling Guide</a><br />
<a href="http://books.zkoss.org/wiki/ZK_Component_Reference/Layouts/Borderlayout">Borderlayout</a><br />
<a href="http://books.zkoss.org/wiki/ZK%20Component%20Reference/Layouts/Hlayout">Hlayout</a><br />
<a href="http://books.zkoss.org/wiki/ZK%20Developer's%20Reference/UI%20Patterns/Hflex%20and%20Vflex">Hflex</a><br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-619908529158146379.post-27242301506834873582012-07-11T11:54:00.000-07:002012-07-19T09:59:19.400-07:00ZK in Action [3] : MVVM - Working Together with ZK Client API<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script><br />
In the previous posts we've implemented the following functionalities with ZK's MVVM:<br />
<ul><li><a href="http://techdojo.blogspot.ca/2012/05/zk-in-action-0-mvvm-load-and-render.html">load data into a table</a></li>
<li><a href="http://techdojo.blogspot.ca/2012/05/zk-in-action-1-mvvm-form-binding.html">save data with form binding</a></li>
<li><a href="http://techdojo.blogspot.com/2012/06/zk-in-action-2-mvvm-update-view.html">delete entries and update the View programmatically</a></li>
</ul><br />
A key distinction between ZK MVVM and ZK MVC implementation wise is that we do not access and manipulate the UI components directly in the controller(ViewModel) class. In this post, we'll see how we can delegate some of the UI manipulation to client side code, as well as how to pass parameters from View to ViewModel.<br />
<br />
<h3>Objective</h3>Build an update function to our simple inventory CRUD feature. Users can edit-in-place entries in the table and given the choice to update or discard the changes made. Modified entries are highlighted in red.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPoe4Qv1adjDWAaw8aQtsilYpQZjf8kPSbHiUT3tpYYKrOWi9Sf09-C8vqiLMc3s2torw0C6Sg_SMDMLqDwm35MJQ0VKAprLWyRm8rPvJW8_jT8wfzlHhPee2ecAl7CfkbnbN8z-5H2I8/s1600/MVVM_update_table.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPoe4Qv1adjDWAaw8aQtsilYpQZjf8kPSbHiUT3tpYYKrOWi9Sf09-C8vqiLMc3s2torw0C6Sg_SMDMLqDwm35MJQ0VKAprLWyRm8rPvJW8_jT8wfzlHhPee2ecAl7CfkbnbN8z-5H2I8/s640/MVVM_update_table.png" width="640" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><h3>ZK Features in Action</h3><ul><li>ZK Client-side APIs</li>
<li>ZK Style Class</li>
<li>MVVM : Pass Parameters from View to ViewModel</li>
</ul><br />
<h3>Implementation in Steps</h3><h4>Enable In-place editing in Listbox so we can edit entries:</h4><pre class="brush:html; highlight=[4];"><listcell>
<textbox inplace="true" value="@load(each.name)" ...</textbox>
</listcell>
....
<listcell>
<doublebox inplace="true" value="@load(each.price)" ...</textbox>
</listcell>
...
</pre><ul><li><i>inplace="true"</i> renders input elements such as Textbox without their borders displaying them as plain labels; the borders appear only if the input element is selected</li>
<li>line 2, 6,"each" refers to each Item object in the data collection</li>
</ul><br />
<h4>Once an entry is edited we want to give users the option to Update or Discard the change. </h4>The Update and Discard buttons need to be visible only if user has made modifications on the Listbox entries. First we define JavaScript functions to show and hide the Update and Discard buttons:<br />
<pre class="brush:html;"><toolbar>
...
<span id="edit_btns" visible="false" ...>
<toolbarbutton label="Update" .../>
<toolbarbutton label="Discard" .../>
</span>
</toolbar>
<script type="text/javascript">
function hideEditBtns(){
jq('$edit_btns').hide();
}
function showEditBtns(){
jq('$edit_btns').show();
}
</script>
...
</pre><ul><li>line 2, we wrap the <b>Update</b> and <b>Discard</b> and set visibility to false<br />
</li>
<li>line 9, 13, we define functions which hide and show the <b>Update</b> and <b>Discard</b> buttons respectively</li>
<li>line 11, 15, we make use of jQuery selector <i>jq( '$edit_btns')</i> to retrieve the ZK widget whose ID is "edit_btns"; notice the selector pattern for a ZK widget ID is '$', not '#'</li>
</ul><br />
<h4>When entries in the Listbox are modified, we'll make the Update/Discard buttons visible and make the modified values red. Once either Update or Discard button is clicked, we'd like to hide the buttons again</h4>Since this is pure UI interactions, we'll make use of ZK's client side APIs:<br />
<pre class="brush:html; highlight=[4];"><style>
.inputs { font-weight: 600; }
.modified { color: red; }
</style>
...
<toolbar xmlns:w="client" >
...
<span id="edit_btns" visible="false" ...>
<toolbarbutton label="Update" w:onClick="hideEditBtns()" .../>
<toolbarbutton label="Discard" w:onClick="hideEditBtns()" .../>
</span>
</toolbar>
<script type="text/javascript">
//show hide functions
zk.afterMount(function(){
jq('.inputs').change(function(){
showEditBtns();
$(this).addClass('modified');
})
});
</script>
...
<listcell>
<doublebox inplace="true" sclass="inputs" value="@load(each.price)" ...</textbox>
</listcell>
...
</pre><ul><li>line 2, we specify a style class for our input elements (Textbox, Intbox, Doublebox, Datebox) and assign it to input elements' sclass attribute, eg. line 26; sclass defines style class for ZK widgets</li>
<li>line 18~20, we get all the input elements by matching their sclass name and assign an onChange event handler. Once the value in an input element is changed, the Update/Discard buttons will become visible and the modified value will be highlighted in red.</li>
<li>line 17, zk.afterMount is run when ZK widgets are created</li>
<li>line 6, we specify the client namespace so we can register client side onClick event listeners with the syntax "w:onClick". Note we can still register our usual onClick event listener that's handled at the server simultaneously.</li>
<li>line 9, 10, we assign client side onClick event listener; the hideEditBtns function would be called to make the buttons invisible again</li>
</ul><br />
<h4>Define a method to store the modified Item objects into a collection so the changes could be updated in batch if user choose to do so:</h4><pre class="brush: java;">public class InventoryVM {
private HashSet<Item> itemsToUpdate = new HashSet<item>();
...
@Command
public void addToUpdate(@BindingParam("entry") Item item){
itemsToUpdate.add(item);
}
</pre><ul><li>line 6, we annotate this method as a command method so it can be invoked from View</li>
<li>line 7, <i>@BindingParam("entry") Item item</i> binds an arbitrarily named parameter called "entry"; we anticipate the parameter would be of type Item</li>
</ul><br />
<h4>Create a method to update the changes made in View to the Data Model</h4><pre class="brush: java;">public class InventoryVM {
private List<Item> items;
private HashSet<Item> itemsToUpdate = new HashSet<item>();
...
@NotifyChange("items")
@Command
public void updateItems() throws Exception{
for (Item i : itemsToUpdate){
i.setDatemod(new Date());
DataService.getInstance().updateItem(i);
}
itemsToUpdate.clear();
items = getItems();
}
</pre><br />
<h4>When modifications are made on Listbox entries, invoke the addToUpdate method and pass to it the edited Item object which in turn is saved to the itemsToUpdate collection</h4><pre class="brush:html;"><listitem>
<listcell>
<doublebox value="@load(each.price)
@save(each.name, before='updateItems')"
onChange="@command('addToUpdate',entry=each)" />
</listcell>
...
</listitem>
</pre><ul><li><i>@save(each.name, before='updateItems')</i> ensures that modified values are not saved unless updateItems is called (ie. when user click the "Update" button)</li>
</ul><br />
<h4>Finally, when user clicks Update, we call the updateItems method to update changes to Data Model. If Discard is clicked, we call getItems to refresh the Listbox without applying any changes</h4><pre class="brush:html;">...
<toolbarbutton label="Update" onClick="@command('updateItems')" .../>
<toolbarbutton label="Discard" onClick="@command('getItems')" .../>
...
</pre><br />
<h3>In a Nutshell</h3><ul><li>Under the MVVM pattern we strive to keep the ViewModel code independent of any View components</li>
<li>Since we don't have direct reference to the UI components in the ViewModel code, we can delegate the UI manipulation (in our sample code, show/hide, style change) code to the client using ZK's client side APIs</li>
<li>We can make use of jQuery selectors and APIs at ZK client side<br />
<li>We can easily pass parameters from View to ViewModel with @BindingParam<br />
</ul>Next up, we'll go over a bit more on ZK Styling before we tackle the MVVM validators and converters. <h3>Reference</h3><button id="view-src-btn" type="button">View Source Code</button> <button id="hide-src-btn" type="button">Hide Source Code</button> <div id="zkmvvm-src"><b>ViewModel (ZK in Action[0]~[3]):</b> <pre class="brush:java;">public class InventoryVM {
private List<Item> items;
private Item newItem;
private Item selected;
private HashSet<Item> itemsToUpdate = new HashSet<Item>();
public InventoryVM(){}
//CREATE
@NotifyChange("newItem")
@Command
public void createNewItem(){
newItem = new Item("", "",0, 0,new Date());
}
@NotifyChange({"newItem","items"})
@Command
public void saveItem() throws Exception{
DataService.getInstance().saveItem(newItem);
newItem = null;
items = getItems();
}
@NotifyChange("newItem")
@Command
public void cancelSave() throws Exception{
newItem = null;
}
//READ
@NotifyChange("items")
@Command
public List<Item> getItems() throws Exception{
items = DataService.getInstance().getAllItems();
for (Item j : items){
System.out.println(j.getModel());
}
Clients.evalJavaScript("zk.afterMount(function(){jq('.inputs').removeClass('modified').change(function(){$(this).addClass('modified');showEditBtns();})});"); //how does afterMount work in this case?
return items;
}
//UPDATE
@NotifyChange("items")
@Command
public void updateItems() throws Exception{
for (Item i : itemsToUpdate){
i.setDatemod(new Date());
DataService.getInstance().updateItem(i);
}
itemsToUpdate.clear();
items = getItems();
}
@Command
public void addToUpdate(@BindingParam("entry") Item item){
itemsToUpdate.add(item);
}
//DELETE
@Command
public void deleteItem() throws Exception{
if (selected != null){
String str = "The item with name \""+selected.getName()+"\" and model \""+selected.getModel()+"\" will be deleted.";
Messagebox.show(str,"Confirm Deletion", Messagebox.OK|Messagebox.CANCEL, Messagebox.QUESTION,
new EventListener<Event>(){
@Override
public void onEvent(Event event) throws Exception {
if (event.getName().equals("onOK")){
DataService.getInstance().deleteItem(selected);
items = getItems();
BindUtils.postNotifyChange(null, null, InventoryVM.this, "items");
}
}
});
} else {
Messagebox.show("No Item was Selected");
}
}
public Item getNewItem() {
return newItem;
}
public void setNewItem(Item newItem) {
this.newItem = newItem;
}
public Item getselected() {
return selected;
}
public void setselected(Item selected) {
this.selected = selected;
}
}
</pre><b>View (ZK in Action[0]~[3]):</b> <pre class="brush:html;"><zk>
<style>
.z-toolbarbutton-cnt { font-size: 17px;} .edit-btns {border: 2px
solid #7EAAC6; padding: 6px 4px 10px 4px; border-radius: 6px;}
.inputs { font-weight: 600; } .modified { color: red; }
</style>
<script type="text/javascript">
function hideEditBtns(){ jq('$edit_btns').hide(); }
function showEditBtns(){ jq('$edit_btns').show(); }
zk.afterMount(function(){ jq('.inputs').change(function(){
$(this).addClass('modified'); showEditBtns(); }) });
</script>
<window apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('lab.sphota.zk.ctrl.InventoryVM')"
xmlns:w="client">
<toolbar width="100%">
<toolbarbutton label="Add"
onClick="@command('createNewItem')" />
<toolbarbutton label="Delete"
onClick="@command('deleteItem')"
disabled="@load(empty vm.selected)" />
<span id="edit_btns" sclass="edit-btns" visible="false">
<toolbarbutton label="Update"
onClick="@command('updateItems')" w:onClick="hideEditBtns()"/>
<toolbarbutton label="Discard"
onClick="@command('getItems')" w:onClick="hideEditBtns()" />
</span>
</toolbar>
<groupbox mold="3d"
form="@id('itm') @load(vm.newItem) @save(vm.newItem, before='saveItem')"
visible="@load(not empty vm.newItem)">
<caption label="New Item"></caption>
<grid width="50%">
<rows>
<row>
<label value="Item Name" width="100px"></label>
<textbox value="@bind(itm.name)" />
</row>
<row>
<label value="Model" width="100px"></label>
<textbox value="@bind(itm.model)" />
</row>
<row>
<label value="Unit Price" width="100px"></label>
<decimalbox value="@bind(itm.price)"
format="#,###.00" constraint="no empty, no negative" />
</row>
<row>
<label value="Quantity" width="100px"></label>
<spinner value="@bind(itm.qty)"
constraint="no empty,min 0 max 999:
Quantity Must be Greater Than Zero" />
</row>
<row>
<cell colspan="2" align="center">
<button width="80px" label="Save" mold="trendy"
onClick="@command('saveItem')" />
<button width="80px" label="Cancel" mold="trendy"
onClick="@command('cancelSave')" />
</cell>
</row>
</rows>
</grid>
</groupbox>
<listbox selectedItem="@bind(vm.selected)" model="@load(vm.items) ">
<listhead>
<listheader label="Name" sort="auto" hflex="2" />
<listheader label="Model" sort="auto" hflex="1" />
<listheader label="Quantity" sort="auto" hflex="1" />
<listheader label="Unit Price" sort="auto" hflex="1" />
<listheader label="Last Modified" sort="auto" hflex="2" />
</listhead>
<template name="model">
<listitem>
<listcell>
<textbox inplace="true" width="110px" sclass="inputs"
value="@load(each.name) @save(each.name, before='updateItems')"
onChange="@command('addToUpdate',entry=each)">
</textbox>
</listcell>
<listcell>
<textbox inplace="true" width="110px" sclass="inputs"
value="@load(each.model) @save(each.model, before='updateItems')"
onChange="@command('addToUpdate',entry=each)" />
</listcell>
<listcell>
<intbox inplace="true" sclass="inputs"
value="@load(each.qty) @save(each.qty, before='updateItems')"
onChange="@command('addToUpdate',entry=each)" />
</listcell>
<listcell>
<doublebox inplace="true" sclass="inputs" format="###,###.00"
value="@load(each.price) @save(each.price, before='updateItems')"
onChange="@command('addToUpdate',entry=each)" />
</listcell>
<listcell label="@load(each.datemod)" />
</listitem>
</template>
</listbox>
</window>
</zk>
</pre></div><ul><li><a href="http://books.zkoss.org/wiki/ZK_Client-side_Reference">ZK Client-side Reference</a></li>
<li><a href="http://books.zkoss.org/wiki/ZK%20Developer's%20Reference/MVVM/Syntax/ViewModel/Parameters/@BindingParam">ZK Developer Reference: @BindingParam</a></li>
</ul><script type="text/javascript">
$('#zkmvvm-src').hide();
$('#hide-src-btn').hide();
$('#view-src-btn').click(function(){$('#zkmvvm-src').show('slow'); $(this).hide(); $('#hide-src-btn').show()});
$('#hide-src-btn').click(function(){$('#zkmvvm-src').hide('slow'); $(this).hide(); $('#view-src-btn').show()});
</script>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-619908529158146379.post-71215985735522715232012-06-11T22:27:00.001-07:002012-07-05T11:37:06.795-07:00ZK in Action [2] : MVVM - Update View ProgrammaticallyIn the previous 2 posts we've used ZK's MVVM functionalities to:<br />
<ul><li><a href="http://techdojo.blogspot.ca/2012/05/zk-in-action-0-mvvm-load-and-render.html">load data into a table</a></li>
<li><a href="http://techdojo.blogspot.ca/2012/05/zk-in-action-1-mvvm-form-binding.html">save data with form binding</a></li>
</ul><br />
<div>We've seen when a method is decorated with the annotation <i>@NotifyChange(<vm property="">)</vm></i>, upon its execution completes, the Binder would be informed of the VM property's changes so that Binder can update the corresponding UI accordingly. </div><br />
<div>In this post, whilst we implement the functionality of item deletion in our inventory, we'll see how we can update UI components programmatically at runtime.</div><br />
<h3>Objective</h3>Build a delete function to our simple inventory CRUD feature.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTFB2tsqqaDg0i4PRx2es8OLk3DtCkiAV0EwfLrcoE1b0_VtUVoHRxnAA33RVIq05cGtiJq9VmbO4CJqngzFV1bbJlzChoPYmv55JPGPm1bfG_kOft0rzVNWObUT64P8W81gM5c63SqrY/s1600/MVVM_delete_confirm.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTFB2tsqqaDg0i4PRx2es8OLk3DtCkiAV0EwfLrcoE1b0_VtUVoHRxnAA33RVIq05cGtiJq9VmbO4CJqngzFV1bbJlzChoPYmv55JPGPm1bfG_kOft0rzVNWObUT64P8W81gM5c63SqrY/s1600/MVVM_delete_confirm.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Select Item in Table, Click "Delete", Confirm Deletion</td></tr>
</tbody></table><br />
<br />
<h3>ZK Feature in Action</h3><br />
<ul><li>MVVM : BindUtils</li>
</ul><br />
<h3>Implement Deletion with MVVM BindUtils</h3>We will:<br />
<ul><li>Add markup for the delete button and assign it an onClick event handler</li>
<li>Implement command method "<i>deleteItem()</i>" in VM</li>
</ul><br />
<b>The Markup</b><br />
<pre class="brush:html; highlight=[4];"><window apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('...InventoryVM')">
<toolbar width="100%">
<toolbarbutton label="Add" onClick="@command('createNewItem')" />
<toolbarbutton label="Delete" onClick="@command('deleteItem')" disabled="@load(empty vm.selected)"/>
</toolbar>
</pre><ul><li>line 5, assign a command method "<i>deleteItem</i>" to the delete button's onClick handler</li>
<li>line 5, "<i>disabled="@(empty vm.selected)"</i>" ensures that the delete button is functional only if an entry in the table has been selected</li>
</ul><br />
<br />
<b><br />
The ViewModel Class</b><br />
<pre class="brush: java; highlight=[3,5];">public class InventoryVM {
private Item selected;
private List<Item> items;
...
@Command
public void deleteItem() throws Exception{
if (selected != null){
String str = "The item with name \""
+selected.getName()
+"\" and model \""
+selected.getModel()
+"\" will be deleted.";
Messagebox.show(str,"Confirm Deletion", Messagebox.OK|Messagebox.CANCEL, Messagebox.QUESTION,
new EventListener<event>(){
@Override
public void onEvent(Event event) throws Exception {
if (event.getName().equals("onOK")){
DataService.getInstance().deleteItem(selected);
items = getItems();
BindUtils.postNotifyChange(null, null, InventoryVM.this, "items");
});
} ...
}
...
}
</pre><br />
<ul><li>line 7, we decorate our <i>deleteItem</i> method with @Command so it can be wired as the onClick event handler in our added markup: <br />
<i><b><toolbarbutton label="Delete" onClick="@command('deleteItem')" /></b></i>;<br />
</li>
<li>line 9, we go ahead with the deletion process only if an item is selected.<br />
</li>
<li>line 16, we show a Messagebox which prompts the user to confirm the deletion of the selected item.</li>
<li>line 20, if user clicks "OK", our program proceeds to delete the selected item.</li>
<li>line 23, we call <i>BindUtils.postNotifyChange(String <b>queueName</b>, String <b>queueScope</b>, Object <b>bean</b>, String <b>property</b>)</i> to update our inventory table. By giving the parameter queueScope a <b>null</b> value, the default desktop queue scope is used. The third and forth argument are given as such since we want to notify the Binder that property "items" in our InventoryVM instance has changed. The Binder would then update the UI (remove the item entry in the inventory table).<br />
</li>
</ul><br />
<h3>Wrap Up</h3>The <i>@NotifyChange</i> annotation lets us update the UI through ZK MVVM's Binder to reflect changes made to the ViewModel properties. The notification is fired when the annotated method finishes executing. In our implementation, we attached an anonymous event listener class to a Messagebox. In this case, after deleteItem is executed, the annotation <i>@NotifyChange("items")</i> would falsely alert the Binder before the event handling is completed. A programmatic way to reflect state changes in ViewModel to the UI resolves this particular problem conveniently.<br />
<br />
Next up, editing the entries with MVVM. <br />
<br />
<h3>Reference</h3><a href="http://books.zkoss.org/wiki/ZK%20Developer's%20Reference/MVVM/ViewModel/Notification#Notify_Programmatically" target="_blank">ZK Deverloper Reference</a>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-619908529158146379.post-88648451394791563752012-05-31T17:40:00.001-07:002012-07-05T11:52:55.989-07:00ZK in Action [1] : MVVM - Form BindingThis is the second episode in our efforts to build a ZK application from the ground up. The previous post dealt with loading and rendering of data into a table using MVVM. In this post, we'll be introduced to ZK MVVM's form binding.<br />
<br />
<h3>
Objective</h3>
We'll build an "Add" function that would enable us to save new entries to the inventory.<br />
<br />
<div>
<div style="text-align: left;">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqv4S-bgoCtGH-VTlCL1pHSXJjtRzzMNeOrrlM5afJagMnAUFfhIb4otoxAEG9dfYRO_QiOWiZkV5Crssf5JCCDck2cjkNCzVia7Nm2ASU-6q-GS6j0yFXaqJBnoOAZp4KF2vTrz2c_UU/s1600/MVVM_save_item.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqv4S-bgoCtGH-VTlCL1pHSXJjtRzzMNeOrrlM5afJagMnAUFfhIb4otoxAEG9dfYRO_QiOWiZkV5Crssf5JCCDck2cjkNCzVia7Nm2ASU-6q-GS6j0yFXaqJBnoOAZp4KF2vTrz2c_UU/s1600/MVVM_save_item.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A Form Appears When "Add" is Clicked</td></tr>
</tbody></table>
</div>
<br />
<br />
<div style="text-align: left;">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Nfb7ucFOxaQ3nECNGHcIL_6s1GOcgdHaR5M48hQbGfcfXQrGNdbB4GaMJU3JUXSWtSQWQj3sBCpt77CSsmE5qZxWtQ2x9dzqFpy2nIHwqgJ1tKfpjbuZJ3OSYmsmuBlghvYWMDYfk7M/s1600/MVVM_save_item_done.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Nfb7ucFOxaQ3nECNGHcIL_6s1GOcgdHaR5M48hQbGfcfXQrGNdbB4GaMJU3JUXSWtSQWQj3sBCpt77CSsmE5qZxWtQ2x9dzqFpy2nIHwqgJ1tKfpjbuZJ3OSYmsmuBlghvYWMDYfk7M/s640/MVVM_save_item_done.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">New Entry is Added When "Save" is Clicked</td></tr>
</tbody></table>
</div>
<br />
<br />
<h3>
ZK Features in Action</h3>
<ul>
<li>MVVM : Save, Form Binding, Conditional Binding</li>
</ul>
<br />
<h3>
Add New Entries with MVVM Form Binding</h3>
we'll need to implement these parts:<br />
<ul>
<li>Enhance our ViewModel POJO</li>
<li>Add UI markup to present a form and decorate the markup with the appropriate annotations</li>
</ul>
<b>The ViewModel Class</b><br />
<pre class="brush: java; highlight=[3,5];">public class InventoryVM {
private List<item> items;
private Item newItem;
@NotifyChange("newItem")
@Command
public void createNewItem(){
newItem = new Item("", "",0, 0,new Date());
}
@NotifyChange({"newItem","items"})
@Command
public void saveItem() throws Exception{
DataService.getInstance().saveItem(newItem);
newItem = null;
items = getItems();
}
@NotifyChange("newItem")
@Command
public void cancelSave() throws Exception{
newItem = null;
}
public List<item> getItems() throws Exception{
items = DataService.getInstance().getAllItems();
return items;
}
}
</pre>
<br />
<ul>
<li>Line 4, we declare an Item object named <i>newItem</i> which will reference the Item instance to be saved to the database.</li>
<li>Line 6, <b>@NotifyChange</b> informs the binder to update the UI on the state of the associated ViewModel's property. <br />
In our UI markup shown below, at line 8, we have a Groupbox annotated with <b>visible="@load(<i>not empty vm.newItem</i>)</b>, hence the Groupbox will become visible once <i>createNewItem</i> assigns an instance of Item to <i>newItem</i>. <br />
Simply put, <b>@NotifyChange</b> refreshes the UI with respect to the updates on ViewModel's properties.</li>
<li>Line 7, we annotate the <i>createNewItem</i> method with <b>@Command</b> and in our UI markup shown below, at line 4, we have a Toolbarbutton with <b>onClick="@commnad(createNewItem)"</b>. So when the Toolbarbutton is clicked, the <i>createNewItem</i> method will be invoked.<br />
</li>
<li>Similarly, from line 12 to 18, we have a saveItem method which is called when its corresponding onClick event is triggered. Once the new Item object is saved to the database cache, we reset the newItem to null and retrieve the new list of items. The changes made to the ViewModel properties <i>newItem</i> (now null again) and <i>items</i> (now with an extra entry) are reflected to the UI using <b>@NotifyChange</b> as before.</li>
</ul>
<b><br />
</b><br />
<b>The Markup</b> <br />
<pre class="brush: html"><window apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('lab.sphota.zk.ctrl.InventoryVM')">
<toolbar>
<toolbarbutton label="Add" onClick="@command('createNewItem')" />
</toolbar>
<groupbox form="@id('itm') @load(vm.newItem)
@save(vm.newItem, before='saveItem')"
visible="@load(not empty vm.newItem)">
<caption label="New Item"></caption>
<grid width="50%">
<rows>
<row>
<label value="Item Name" width="100px"></label>
<textbox id="name" value="@bind(itm.name)" />
</row>
<row>
<label value="Model" width="100px"></label>
<textbox value="@bind(itm.model)" />
</row>
<row>
<label value="Unit Price" width="100px"></label>
<decimalbox value="@bind(itm.price)" format="#,###.00"
constraint="no empty, no negative" />
</row>
<row>
<label value="Quantity" width="100px"></label>
<spinner value="@bind(itm.qty)"
constraint="no empty,min 0 max 999:
Quantity Must be Greater Than Zero" />
</row>
<row>
<cell colspan="2" align="center">
<button width="80px" label="Save"
onClick="@command('saveItem')" mold="trendy" />
<button width="80px" label="Cancel"
onClick="@command('cancelSave')" mold="trendy" />
</cell>
</row>
</rows>
</grid>
</groupbox>
<listbox>
...
</listbox>
</window>
</pre>
<ul>
<li>Line 1, we apply ZK's default implementation of its BindComposer. It is responsible for instantiating our ViewModel and Binder instances.</li>
<li>Line 2, we supply the full class name of the ViewModel we wish to instantiate and give it an ID for future reference</li>
<li>Line 4, we assign our ViewModel's "command method" <i>createNewItem</i> as the onClick event handler for the toolbar button.</li>
<li>Line 6, the property newItem in ViewModel is made referenceable throughout the Groupbox using the ID "itm".</li>
<li>Line 6,7, by using form binding, to avoid invalid or incomplete data saved to the ViewModel property, entries in the form are saved to a temporary object until the command method <i>saveItem</i> is called.<br />
</li>
<li>Line 8, we show the Groupbox to enter a new Item entry only user has clicked the "Add" button; which in turn invokes <i>createNewItem</i> method and assigns the VM property newItem an instance of Item with default value(empty strings and 0s).<br />
</li>
<li>Line 14, 18, 22, 27, we bind the Item properties with the input elements. <b>@bind</b> is effectively equivalent to <b>@load</b> plus <b>@save.</b></li>
</ul>
<br />
<h3>
In a Nuteshell</h3>
To sum up in point form:<br />
<br />
<ul>
<li>Using form binding avoids directly modifying data in ViewModel properties by saving form entries to a temporary object. Data is written to the ViewModel properties only if the condition specified is satisfied; in our example, only if the <i>saveItem</i> method is invoked. </li>
<li> <b>@Command</b> annotation allows the binder to map UI event handlers to ViewModel command methods.</li>
<li><b>@NotifyChange</b> informs the binder which ViewModel properties had been modified after the command method is executed so changes in data can then be reflected on the UI.</li>
<li>We can assign values to any of UI components' attributes at run-time via MVVM binding to manipulate parameters such as visibility, style, disable/enable, etc.</li>
</ul>
<div>
In this post, we've not seen how data entries are validated. Before that, we'll implement the delete and edit functionalities in the next post.</div>
<br />
<h3>
Reference</h3>
<a href="http://books.zkoss.org/wiki/ZK%20Developer's%20Reference/MVVM" target="_blank">ZK Developer Reference</a></div>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-619908529158146379.post-48611347435292538712012-05-30T05:43:00.000-07:002012-07-05T11:44:15.985-07:00ZK in Action [0] : MVVM - Load and Render DataA <a href="http://techdojo.blogspot.ca/2012/03/jquery-selector-inspired-controller-in.html">previous post</a> had briefly introduced the RIA framework ZK and how its CSS Selector inspired controller mechanism alleviates some of the burdens that comes with UI changes by making the task of referencing UI components in the controller class a relatively flexible affair.<br />
<br />
We then explored how the <a href="http://techdojo.blogspot.ca/2012/04/first-look-at-mvvm-in-zk-6.html" target="_blank">MVVM</a> patterns in ZK allows a single ViewModel to serve different views in the last post.<br />
<br />
This post marks the beginning of a series of posts that will go through steps in building a simple application from the ground up using ZK.<br />
<br />
<h3>
Objective</h3>
For now, we'll build a simple inventory management feature which is limited only to the loading and rendering of a data collection from a database into a table.<br />
<br />
<h3>
ZK Features in Action</h3>
<ul>
<li>MVVM : Load</li>
<li>Template Tag</li>
</ul>
<br />
<h3>
Load and Render Data into a Table with MVVM</h3>
Assume there's a collection of objects named "Item" and there's a DataService class which takes care of caching and communication with the database (MongoDB and Morphia).<br />
<pre class="brush: java;">@Entity("items")
public class Item {
@Id
private ObjectId id;
private String name;
private String model;
private int qty;
private float price;
private Date datemod;
// getters & setters
</pre>
<br />
To render data into a table as shown below in ZK, we'll need to implement these parts:<br />
<ul>
<li>A POJO that will serve as our ViewModel</li>
<li>A ZK markup file as our presentation</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgkOtbDbocBHdlWXamNFrSLeVn0E87a2nrGFIZtiXwrVIUSlbaFTRAKYvkEGd8ccA_QmLeiZeeGaeSFr-MkGklLFi01wL_-2p4Fk1_HdlpwRdggrDeSIzg1_KHST0MBr8QFyPnlac7kfw/s1600/MVVMloaditems.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgkOtbDbocBHdlWXamNFrSLeVn0E87a2nrGFIZtiXwrVIUSlbaFTRAKYvkEGd8ccA_QmLeiZeeGaeSFr-MkGklLFi01wL_-2p4Fk1_HdlpwRdggrDeSIzg1_KHST0MBr8QFyPnlac7kfw/s640/MVVMloaditems.png" width="640" /></a></div>
<br />
<b>The ViewModel Class</b><br />
<pre class="brush: java; highlight=[3,5];">public class InventoryVM {
private List<item> items;
public List<item> getItems() throws Exception{
items = DataService.getInstance().getAllItems();
return items;
}
}
</pre>
<br />
<ul>
<li>Line 3, the list of items needs to be declared as a property of the VM class</li>
<li>Line 5, we need to provide a getter method so the Binder can retrieve the list of items. To recap, the Binder holds reference to the UI components and the ViewModel so it can keep data on both sides in sync as well as call command methods in ViewModel as events are triggered in View.</li>
</ul>
<br />
<b>The Markup</b><br />
<pre class="brush: html"><window apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('lab.sphota.zk.ctrl.InventoryVM')">
<listbox model="@load(vm.items) ">
<listhead>
<listheader label="Name" />
<listheader label="Model" />
<listheader label="Quantity" />
<listheader label="Unit Price"/>
<listheader label="Last Modified" />
</listhead>
<template name="model" var="item" >
<listitem>
<listcell>
<textbox value="@load(item.name)" inplace="true" />
</listcell>
<listcell>
<textbox value="@load(item.model)" inplace="true" />
</listcell>
<listcell>
<spinner value="@load(item.qty)" inplace="true" />
</listcell>
<listcell>
<decimalbox value="@load(item.price)" inplace="true"
format="#,###.00"/>
</listcell>
<listcell label="@load(item.datemod)" />
</listitem>
</template>
</listbox>
</window>
</pre>
<br />
<ul>
<li>Line 1, we apply ZK's default implementation of its BindComposer. It is responsible for instantiating our VM instance as well as the Binder instance.</li>
<li>Line 2, we supply the full class name of the ViewModel we wish to instantiate and give it an ID (in this case, 'vm') for future reference</li>
<li>Line 3, we assign a data model, which we made as a property of our ViewModel instance, to the Listbox.</li>
<li>Line 11, we instruct the Template component to iterate through the given collection. We also declare a variable called "item" which will iteratively take on each Item object inside our collection. Alternatively, we can omit the variable declaration and use the keyword "each" to reference the data object (Item).</li>
<li>Line 14, 17, 20, 23, 26, we retrieve the Item properties which we'd like to be displayed in the Listbox.</li>
<li>Here we use input elements (Textbox, Spinner, Decimalbox) inside the Listcells in anticipation of our future implementation of an editable table. The attribute "inplace=true" will render these input elements as regular labels while they're not selected.</li>
</ul>
<br />
<h3>
Wrap Up</h3>
ZK Binder is central to the workings of ZK MVVM. It holds references to both the UI components and the ViewModel. The ViewModel class is just a POJO where we declare and assign our data models. It exposes getter methods so Binder can retrieve and bind data to their respective annotated UI components. The template tag then allows us to iteratively render UI components with respect to the data model. In our case, a row of 5 Listcells with each cell holding a bean property is rendered iteratively through the bean collection using the template tag.<br />
<br />
In the next post, we'll implement an "Add" feature so we can save new entries to our existing inventory using MVVM's form binding.<br />
<br />
<h3>
Reference</h3>
<a href="http://books.zkoss.org/wiki/ZK%20Developer's%20Reference/MVVM" target="_blank">ZK Developer Reference</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-619908529158146379.post-53397514028443230372012-04-30T18:22:00.000-07:002012-05-07T15:30:15.558-07:00A First Look at MVVM in ZK 6<h3>
MVVM vs. MVC</h3>
In a <a href="http://techdojo.blogspot.ca/2012/03/jquery-selector-inspired-controller-in.html" target="_blank">previous post</a> we've seen how the Ajax framework ZK adopts a CSS selector inspired Controller for wiring UI components in View and listening to their events. Under this ZK MVC pattern, <b>the UI components in View need not to be bound to any Controller methods or data objects.</b> The flexibility of using selector patterns as a mean to map View states and events to the Controller makes code more adaptive to change.<br />
<br />
MVVM approaches separation of concern in a reverse direction. Under this pattern, a View-Model and a binder mechanism take place of the Controller. The binder maps requests from View to action logic in View-Model and updates any value (data) on both sides, allowing the<b> View-Model to be independent of any particular View.</b><br />
<br />
<h3>
Anatomy of MVVM in ZK 6</h3>
The below is a schematic diagram of ZK 6's MVVM pattern:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiLKzPw02cpzoNEh2DZ1gUb7xRCkc5ifFqV7ApBMF_VVzRObIrmvcYCbGyqAjkHGodwUVN0PAxlXASUaqNJVIZUfnm7QpVutkifTsI1EakQCGnENJ4XC4h2YDyWFKGFAng9A-qQRdFmxs/s1600/ZK6MVVM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiLKzPw02cpzoNEh2DZ1gUb7xRCkc5ifFqV7ApBMF_VVzRObIrmvcYCbGyqAjkHGodwUVN0PAxlXASUaqNJVIZUfnm7QpVutkifTsI1EakQCGnENJ4XC4h2YDyWFKGFAng9A-qQRdFmxs/s640/ZK6MVVM.png" width="640" /></a></div>
Here are some additional points that's not conveyed in the diagram:<br />
BindComposer:<br />
<ul>
<li>implements ZK's standard controller interfaces (Composer & ComposerExt)</li>
<li>the default implementation is sufficient, no modifications necessary</li>
</ul>
View:<br />
<ul>
<li>informs binder which method to call and what properties to update on the View-Model</li>
</ul>
View-Model:<br />
<ul>
<li>just a POJO</li>
<li>communication with the binder is carried out via Java Annotation</li>
</ul>
<br />
<h3>
MVVM in Action</h3>
Consider the task of displaying a simplified inventory without knowledge of the exact UI markup. An inventory is a collection of items, so we have the object representation of such:<br />
<br />
<pre class="brush: java">public class Item {
private String ID;
private String name;
private int quantity;
private BigDecimal unitPrice;
//getters & setters
}
</pre>
<br />
It also makes sense to expect that an item on the list can be selected and operated on. Thus based on our knowledge and assumptions so far, we can go ahead and implement the View-Model.<br />
<br />
<pre class="brush: java">public class InventoryVM {
ListModelList<Item> inventory;
Item selectedItem;
public ListModelList<Item> getInventory(){
inventory = new ListModelList<Item>(InventoryDAO.getInventory());
return inventory;
}
public Item getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(Item selectedItem) {
this.selectedItem = selectedItem;
}
}
</pre>
<br />
Here we have a typical POJO for the View-Model implementation, data with their getters and setter.<br />
<br />
<h4>
View Implementation, "Take One"</h4>
Now suppose we later learned the requirements for the View is just a simple tabular display:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs90QnmrZ1jzZDXYkuJiOOczQ2Qndb8savgkprDPK7WQGC6MyqDMVTzMeB-7GTGRKPoeDSARfYfkvGxXdGbu1l01NdhCa12BJnBfFxHaJ7wS9TvhtvsDE4RsDgfPDuN7xZ_MmUbL8gLac/s1600/inventoryUI2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs90QnmrZ1jzZDXYkuJiOOczQ2Qndb8savgkprDPK7WQGC6MyqDMVTzMeB-7GTGRKPoeDSARfYfkvGxXdGbu1l01NdhCa12BJnBfFxHaJ7wS9TvhtvsDE4RsDgfPDuN7xZ_MmUbL8gLac/s640/inventoryUI2.png" width="640" /></a></div>
<br />
A possible mark-up to achieve the UI as indicated above is:<br />
<pre class="brush: html"><window title="Inventory" border="normal" apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('lab.zkoss.mvvm.ctrl.InventoryVM')" >
<listbox model="@load(vm.inventory)" width="600px" >
<auxhead><auxheader label="Inventory Summary" colspan="5" align="center"/> </auxhead>
<listhead>
<listheader width="15%" label="Item ID" sort="auto(ID)"/>
<listheader width="20%" label="Name" sort="auto(name)"/>
<listheader width="20%" label="Quantity" sort="auto(quantity)"/>
<listheader width="20%" label="Unit Price" sort="auto(unitPrice)"/>
<listheader width="25%" label="Net Value"/>
</listhead>
<template name="model" var="item">
<listitem>
<listcell><label value="@load(item.ID)"/></listcell>
<listcell><label value="@load(item.name)"/></listcell>
<listcell><label value="@load(item.quantity)"/></listcell>
<listcell><label value="@load(item.unitPrice)"/></listcell>
<listcell><label value="@load(item.unitPrice * item.quantity)"/></listcell>
</listitem>
</template>
</listbox>
</window>
</pre>
<br />
Let's elaborate a bit on the mark-up here. <br />
<br />
<ul>
<li>At line 1, we apply the default BindComposer to the Window component which makes all children components of the Window subject to the BindComposer's effect.</li>
<li>On the following line, we instruct the BindComposer which View-Model class to instantiate and we give the View-Model instance an ID so we could make reference to it.</li>
<li>Since we're loading a collection of data onto the Listbox, at line 3 we assign the property "inventory" of our View-Model instance, which is a collection of the Item objects, to Listbox's attribute "model". </li>
<li>At line 12, we then make use of the model on our Template component. Template iterates its enclosed components according to the model it receives. In this case, we have 5 list items which makes up a row in the Listbox. </li>
<li>In each Listcell, we load the properties of each object and display them in Labels.</li>
</ul>
Via ZK's binding system, we were able to access data in our View-Model instance and load them in View using annotations. <br />
<br />
<h4>
View Implementation, "Take Two"</h4>
Suppose later in development, it's agreed that the current tabular display takes too much space in our presentation and we're now asked to show the details of an item only when the item is selected in a Combobox, as shown below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRjGtOjdNNDCzy1n-GwLN1QBcBR-lvjoXxBtxW8JuIAB3qbcynFH2vNFz3fpTIsBsOnsdZltL6SdF-hnbLgU6eerAzNOUx_u9DgjR7imViy5TnsFDzp5dnKmnRw_YN8cslkUSUaI2Cj64/s1600/inventoryUI1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRjGtOjdNNDCzy1n-GwLN1QBcBR-lvjoXxBtxW8JuIAB3qbcynFH2vNFz3fpTIsBsOnsdZltL6SdF-hnbLgU6eerAzNOUx_u9DgjR7imViy5TnsFDzp5dnKmnRw_YN8cslkUSUaI2Cj64/s1600/inventoryUI1.png" /></a></div>
<br />
Though both the presentation and behaviour(detail is shown only upon user's selection) differ from our previous implementation, the View-Model class needs not be heavily modified. Since an item's detail will be rendered only when it is selected in the Combobox, it's obvious that we'd need to handle the "onSelect" event, let's add a new method <b>doSelect</b>:<br />
<pre class="brush: java; highlight: [6,7,8]">public class InventoryVM {
ListModelList<Item> inventory;
Item selectedItem;
@NotifyChange("selectedItem")
@Command
public void doSelect(){ }
//getters & setters
}
</pre>
<br />
A method annotated with @Command makes it eligible to be called from our mark-up by its name, in our case:<br />
<br />
<pre class="brush: html"><combobox onSelect="@command('doSelect')" >
</pre>
<br />
The annotation @NotifyChange("selectedItem") allows the property <b>selectedItem</b> to be updated <b>automatically</b> whenever user selects a new Item from the Combobox. For our purposes, no addition implementation is needed for the method doSelect. With this bit of change done, we can now see how this slightly-modified View-Model would work with our new mark-up:<br />
<br />
<pre class="brush: html"><window title="Inventory" border="normal" apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('lab.zkoss.mvvm.ctrl.InventoryVM')" width="600px">
...
<combobox model="@load(vm.inventory)"
selectedItem="@bind(vm.selectedItem)"
onSelect="@command('doSelect')" >
<template name="model" var="item">
<comboitem label="@load(item.ID)"/>
</template>
<comboitem label="Test"/>
</combobox>
<listbox visible="@load(not empty vm.selectedItem)" width="240px">
<listhead>
<listheader ></listheader>
<listheader ></listheader>
</listhead>
<listitem>
<listcell>
<label value="Item Name: " />
</listcell>
<listcell>
<label value="@load(vm.selectedItem.name)" />
</listcell>
</listitem>
<listitem>
<listcell>
<label value="Unit Price: " />
</listcell>
<listcell>
<label value="@load(vm.selectedItem.unitPrice)" />
</listcell>
</listitem>
<listitem>
<listcell>
<label value="Units in Stock: " />
</listcell>
<listcell>
<label value="@load(vm.selectedItem.quantity)" />
</listcell>
</listitem>
<listitem>
<listcell>
<label value="Net Value: " />
</listcell>
<listcell>
<label value="@load(vm.selectedItem.unitPrice * vm.selectedItem.quantity)" />
</listcell>
</listitem>
</listbox>
...
</window>
</pre>
<br />
<br />
<ul>
<li>At line 4, we load the data collection inventory to the Combobox's model attribute so it can iteratively display the ID for each Item object in the data model using the Template component declared on line 7. </li>
<li>At line 5, the selectedItem attribute points to the most recently selected Item on that list of Item objects</li>
<li>At line 6, we've mapped the onSelect event to the View-Model's doSelect method</li>
<li>At line 12, we make the Listbox containing an Item's detail visible only if the selectedItem property in View-Model is not empty (selectedItem will remain empty until an item is selected in the Combobox).</li>
<li>The selectedItem's properties are then loaded to fill out the Listbox.</li>
</ul>
<br />
<h3>
Recap</h3>
Under the MVVM pattern, our View-Model class exposes its data and methods to the binder; there's no reference made to any particular View component. The View implementations access data or invoke event handlers via the binder. <br />
<br />
In this post, we're only exposed to the fundamental workings of ZK's MVVM mechanisms. The binder is obviously not restricted to just loading data from the View-Model. In addition to saving data from View to ViewModel, we can also inject data converters and validators in the mix of View to View-Model communications. The MVVM pattern may also work in conjunction with the MVC model. That is, we can also wire components and listen to fired-events via the MVC Selector mechanism if we wish to do so.<br />
<br />
We'll dig into some of these topics at a later time.<br />
<br />
<h3>
Reference</h3>
<a href="http://books.zkoss.org/wiki/ZK%20Developer's%20Reference/MVVM" target="_blank">ZK Developer's Reference</a>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-619908529158146379.post-33798858362112623872012-03-27T18:22:00.000-07:002012-04-02T10:03:58.487-07:00JavaScript Closure Under the HoodClosure is perhaps the most talked about feature in JavaScript. This post will attempt to deal with just enough of the theoretical aspects for us to appreciate the inner workings of the language behaviour we take granted for. The context of this discussion is not specific to any JavaScript engine implementation.<br />
<br />
<h4>Omni-Closures</h4><br />
In his book <i>Secrets of the JavaScript Ninja</i>, John Resig gave an informal description of closure as "A closure is a way to access and manipulate external variables from within a function."<br />
<div>Here is a rudimentary manifestation of closure that echoes the above description:<br />
<br />
<pre class="brush: js">var y = 6; // y is a global variable
function getSum(x){
var z = 0; // z is a local variable of
return x + y + z; // getSum, whereas y is
} // an external variable to getSum
getSum(4); //returns 10
</pre></div><br />
The variable <b>y</b> is not a local variable of getSum and yet it's been operated on within getSum. Closures are at work even for the most trivial code we'd write and take granted for.<br />
<br />
A more explicit show of closure is when the local variables of an outer function remains to be referenced by the inner function even after the outer function's execution is complete:<br />
<br />
<pre class="brush: js">function setOperators(y){ // outer function
var z = 5;
function getSum(x){ //inner function
return x + y + z;
}
return getSum;
}
var getSumRef = setOperators(4);//outer function's execution is complete and returns the function getSum
//
getSumRef(1); //returns 10
</pre><br />
<h4>Function Scope?</h4><br />
Simply put, the scope for an entity Z refers to what other entities Z has access to. In JavaScript, a variable is said to have function scope. Instead of a rigorous but lengthy definition for it, let's consider this structure instead:<br />
<br />
<pre class="brush: js">var i = 1;
function x(a){
var j = 1;
function y(){
var k = 1;
}
}
</pre><br />
In the perspective of function <b>x</b>, var <b>j</b> and function <b>y</b> are accessible because they are declared within <b>x</b>, that is, they are local to <b>x</b>. Function <b>x</b> cannot access var <b>k</b> since <b>k</b> is within function <b>y</b>, hence local to <b>y</b>, but not to <b>x</b>. So far, functions x and y's behaviour adheres to that determined by their respective scopes.<br />
<br />
However, by the merits of closure, functions can access variables outside of its local scope. Specifically, function y can access var <b>j</b>, and function <b>x</b> can access var <b>i</b>.<br />
<br />
A closure is formed for function <b>y</b> which preserves the environment which <b>y</b> was created in, allowing <b>y</b> continue to have access to that environment. The variable <b>j</b> and argument <b>a</b> (argument for function x) are two of the constituents in this environment.<br />
<br />
<h4>A Naive Visualization of Scope and Environment</h4><br />
Albeit neglecting some important details, sometimes a casual visualization can provide a mental picture that would eventually lead to a fuller understanding. So here is the attempt:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMd7lrTCtAJnSqN18NO0MvJzb8ZwONKjc44l1rWHucaZ_tcM361rZQcb0CuXkOwqb5W5VtRMQVFeULXzYB6Xz8bzTsoqqattYzzWRTFBHOLLuHhMuPpeGe5mvkSCaI_jqupwmw_UeXEoE/s1600/js_scope.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMd7lrTCtAJnSqN18NO0MvJzb8ZwONKjc44l1rWHucaZ_tcM361rZQcb0CuXkOwqb5W5VtRMQVFeULXzYB6Xz8bzTsoqqattYzzWRTFBHOLLuHhMuPpeGe5mvkSCaI_jqupwmw_UeXEoE/s1600/js_scope.png" /></a></div><br />
For function x:<br />
<ul><li>local scope is the yellow area</li>
<li>environment is the blue area</li>
<li>x can access variables in yellow(local) and blue(environment), but not in green</li>
</ul><br />
For function y:<br />
<ul><li>local scope is the green area</li>
<li>environment is the yellow area, plus the blue area</li>
<li>y can access variables in green(local), yellow(environment), and blue(environment)</li>
</ul><br />
Now we're better equipped to appreciate Wikipedia's definition of closure:<br />
"<b>A closure is a function together with a referencing environment for the non-local variables of that function.</b>"<br />
<br />
<h4>Inner Workings of Closure</h4><br />
For ECMAScript, the proper name for this referencing environment '<b>e</b>' is called an Activation Object when <b>e</b> is the local scope of a function, and a Global Object when <b>e</b> is the global scope. The activation object keeps local variables, named arguments, the <span style="font-family: 'Courier New', Courier, monospace;">arguments</span> collection and <span style="font-family: 'Courier New', Courier, monospace;">this</span> as key-value pairs.<br />
Every time a function is being executed, an internal object called Execution Context is created for that specific execution. Execution context keeps a list of all activation objects and global object for the respective function being executed.<br />
<br />
For instance, for our previous sample snippet:<br />
<pre class="brush: js">function setOperators(y){
var z = 5;
function getSum(x){
return x + y + z;
}
return getSum;
}
var getSumRef = setOperators(4);
getSumRef(1); //returns 10
</pre><br />
The corresponding execution context would be:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmSuVkBMQWmq3SMtxizpys1RZ_cJeQ0Ede5VUvdlGZ3SxKo-Crlu6IV3oTTqSwmN7-Au0qD8d5RdzcVOuaMqipaOeSoIqafrqIsyj3dW4KDUsSyuJLFvxniHuTU27ufksCo1YqTBL60lo/s1600/Execution_Context.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmSuVkBMQWmq3SMtxizpys1RZ_cJeQ0Ede5VUvdlGZ3SxKo-Crlu6IV3oTTqSwmN7-Au0qD8d5RdzcVOuaMqipaOeSoIqafrqIsyj3dW4KDUsSyuJLFvxniHuTU27ufksCo1YqTBL60lo/s1600/Execution_Context.png" /></a></div><br />
When a closure is not needed for a function to reference its non-local variables, the function's execution context is discarded along with its activation objects. However, since the inner function getSum references non-local variable z, and argument y, a closure is created.<br />
<br />
The closure makes a reference to the activation object for the "var getSumRef = setOperators(4)" execution context. Hence, even when setOperators' execution is completed, getSumRef remains to have access to the variables and the function getSum for evaluating the addition for us.<br />
<br />
<h4>Digging Deeper(and Broader) for the Whole Picture</h4><br />
Here we've really only seen an expansion on the term "environment" in the context of a typical closure definition. To get a complete view of how scopes are managed and what function execution entails, refer to the following excellent resources:<br />
<a href="http://shop.oreilly.com/product/9780596802806.do" target="_blank">High Performance JavaScript</a><br />
<a href="http://jibbering.com/faq/notes/closures/">http://jibbering.com/faq/notes/closures/</a><br />
<a href="http://perfectionkills.com/understanding-delete/">http://perfectionkills.com/understanding-delete/</a><br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-619908529158146379.post-8332056028735785212012-03-18T14:59:00.002-07:002012-05-07T15:30:29.674-07:00jQuery Selector Inspired Controller in ZK 6's MVC PatternThe MVC pattern is adopted pervasively among Web frameworks. Various flavours exist for the pattern but the common goal is to achieve separation of concerns.<br />
<br />
Under the ZK framework, MVC implementation ultimately requires the Controller to gain reference to, and listen events coming from, the UI components in View. An interesting bit of ZK 6's MVC pattern is the CSS/jQuery Selector inspired mechanism in its Controller that makes this plumbing task simpler and more flexible.<br />
<br />
<h3>ZK Primer</h3><br />
In simplicity, ZK is a component based and event driven Ajax Java framework. Understanding this basic description alone is enough to take us through its MVC pattern.<br />
<br />
<h4>Component based</h4>A component either declared in XML or in Java has its state maintained as a POJO in the JVM. A component is then rendered with a set of JavaScript instructions at client side.<br />
<div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdmg6iy8i5rb3e1qmeMAKDU9z25viPLPkpDimN2CCGEcvMQaVX3d55hiU08ZDiWX1sL7Z2dLMKABKOqRxpEhiTiWV7Pu5c966yZJ5t5KU6KrA5nD893pijuQhkseqyXk4lFUUc-75a3kw/s1600/ZK-comp-render.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdmg6iy8i5rb3e1qmeMAKDU9z25viPLPkpDimN2CCGEcvMQaVX3d55hiU08ZDiWX1sL7Z2dLMKABKOqRxpEhiTiWV7Pu5c966yZJ5t5KU6KrA5nD893pijuQhkseqyXk4lFUUc-75a3kw/s640/ZK-comp-render.png" width="640" /></a></div><br />
<br />
<h4>Event Driven</h4>Each UI component can listen to event(s). There's a variety of ways to register event listeners to the components.<br />
Just to name a few here,<br />
in XML:<br />
<pre class="brush: html"><button onclick="...">
</button></pre>in Java:<br />
<pre class="brush: java">Button btn = new Button();
btn.addEventListener("onClick", new EventListener(){...});
</pre><br />
<h4>MVC Nomenclature in ZK</h4>The component declarations make up the View. Although it's possible to construct the UI in Java, akin to GWT or Swing, most would prefer writing mark-up in XML. A ZUL in ZK is an XML compliant page that contains the UI mark-up. One can consider a ZUL page as an Ajax enabled JSP page.<br />
<br />
The Controller in ZK is a Java class that implements the Composer interface or extends any one of Composer's implementations. SelectorComposer is the target of our investigation in this post.<br />
<br />
<h3>Selector Inspired Controller in Action</h3><br />
Consider a simple window that prompts a user to enter her name, email address, and select the journal she'd like to subscribe:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKIHPHpOiMEU1IBxMsAODTjcdP-ygOheujY81AlLMuhbBAuMS2SkLjrEcGkeQSt5XH0AUWzKM2zYO1BiKHZRLKFYD53ETA9QvgXz9HeiCjUzByOvWGRmLto4ohKAqpAe3JhU8uYfYmI7c/s1600/ui.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKIHPHpOiMEU1IBxMsAODTjcdP-ygOheujY81AlLMuhbBAuMS2SkLjrEcGkeQSt5XH0AUWzKM2zYO1BiKHZRLKFYD53ETA9QvgXz9HeiCjUzByOvWGRmLto4ohKAqpAe3JhU8uYfYmI7c/s1600/ui.png" /></a></div><br />
We'll examine how the server-side selector mechanism works in our controller class as we implement the following features:<br />
<ol><li>Displaying a list of the available journals for subscription in a combo box</li>
<li>Clear all fields in this simple form when the "Clear" button is clicked</li>
</ol><br />
Let's first see the components in mark-up which our controller will work with:<br />
<pre class="brush: html"><grid apply="lab.zkoss.mvc.SubscriptionComposer">
...
<rows>
<row>
<label value="User Name"/>
<textbox mold="rounded"/>
</row>
<row>
<label value="email"/>
<textbox mold="rounded"/>
</row>
<row>
<cell ...>
<label value="Please subscribe me to "></label>
<combobox model="${journalListModel}">
<template name="model">
<comboitem label="${each.title}"/>
</template>
</combobox>
</cell>
</row>
<row>
<cell ...>
<button label="Clear" ..."/>
<button label="Submit" ..."/>
</cell>
</row>
</rows>
</grid>
</pre><br />
In our controller class, to implement the said features under the ZK framework, we'd need to gain reference to the UI components so the list of available journals can be rendered in the combo box and the onClick event for the Clear button can be handled.<br />
<br />
<pre class="brush: java">public class SubscriptionComposer extends SelectorComposer{
@Wire("combobox")
Combobox journalbox;
@Wire("textbox, combobox")
List<InputElement> inputs;
public void doAfterCompose(Component comp) throws Exception{
super.doAfterCompose(comp);
JournalDAO jdao = new JournalDAO();
List<Journal> journalList = jdao.findAll();
ListModelList journalListModel = new ListModelList(journalList);
journalbox.setModel(journalListModel);
}
@Listen("onClick = button[label='Clear']")
public void clearAll(){
for(InputElement i:inputs) i.setText("");
}
}
</pre>Let's elaborate on how selectors are used.<br />
<br />
<h4>The Controller's Scope</h4>When a controller is "applied" to a component, all of the component's children components also become accessible to the controller. <br />
<br />
In our implementation, the grid component is applied with our controller:<br />
<pre class="brush: html"><grid apply="lab.zkoss.mvc.SubscriptionComposer">
...
</grid>
</pre>Hence the grid and all of its children components define the scope which our controller SubscriptionComposer can take effect.<br />
<br />
<h4>Component Wiring</h4>The @Wire annotation on line 3 and 6 take in a CSS selector pattern as its parameter. With the pattern "<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">combobox</span>, the annotation associates the sole combo box in our UI mark-up with the Combobox instance, <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">journalbox</span> declared in the controller class.<br />
One of the many alternatives to achieve the same exact wiring is to give the Combox an ID, for instance:<br />
<br />
<pre class="brush: html"><combobox id="thisworks2">
...
</combobox>
</pre>and the parameter for the annotation would be:<br />
<pre class="prettyprint linenums">@Wire("#thisworks2")
Combobox journalbox;
</pre><br />
<h4>Component Initialization</h4>Once we've obtained references to the UI components in View, we could initialize them accordingly.<br />
The doAfterCompose method allows developers to insert instructions to be executed right after the component under effect and its children are created. It's a method invoked by the framework and must be implemented for all classes implementing the Composer interface; such as the SelectorComposer class which we're extending our SubscriptionComposer from.<br />
<br />
For our hypothetical feature, we need to initialize our combo box by populating it with a list of journals available for subscription.<br />
<pre class="brush: java">@Wire("combobox")
Combobox journalbox;
...
public void doAfterCompose(Component comp) throws Exception{
super.doAfterCompose(comp);
JournalDAO jdao = new JournalDAO();
List<Journal> journalList = jdao.findAll();
ListModelList<Journal> journalListModel = new ListModelList(journalList);
journalbox.setModel(journalListModel);
}
</pre><br />
On line 11, the combo box which we obtained reference to via the selector mechanism, is given the model data we prepared on line 10. ListModelList is a wraper class that enables changes made in its wrapped collection to be updated on its host UI component accordingly.<br />
<br />
<pre class="brush: html"><combobox model="${journalListModel}">
<template name="model">
<comboitem label="${each.title}"/>
</template>
</combobox>
</pre><br />
Once the combo box is supplied with a list model, the template tag will iteratively create a combo item for each entry in the list model.<br />
<br />
<h4>Event Listening</h4>The @Listen annotation adds method clearAll, as an event listener for the onClick event, to the button matching the pattern <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">button[label="Clear"]</span>.<br />
<br />
<pre class="brush: java">@Wire("textbox, combobox")
List<InputElement> inputs;
@Listen("onClick = button[label='Clear']")
public void clearAll(){
for(InputElement i:inputs) i.setText("");
}
</pre><br />
As before, there're many alternatives to the selector pattern shown here. One possibility is <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">cell:first-child button</span>, since the "Clear" button is the only component that matches this pattern.<br />
<br />
<pre class="brush: html"><cell ...>
<button label="Clear" ..."/>
<button label="Submit" ..."/>
</cell>
</pre><br />
The brevity of the clearAll method is made possible because a single annotation @Wire("textbox, combobox") in fact wired all fields in the UI to a list of ZK components.<br />
<br />
<h3>In a Nutshell</h3><br />
In a typical ZK controller class implementation, before we can initialize a UI component, listen to its events, or change its state, we must first obtain a reference to that component.<br />
This CSS/jQuery selector inspired controller gives us great flexibility in referencing the UI components of interest. A reference can be made by matching a component's ID, class name, component attributes, or by traversing through the component tree.<br />
With this flexibility, changes made in the UI cause us minimum grief since the controller code can be updated as easily as coming up with new selector patterns.<br />
<br />
<h3>References</h3><a href="http://books.zkoss.org/wiki/Small%20Talks/2011/January/Envisage%20ZK%206:%20An%20Annotation%20Based%20Composer%20For%20MVC">ZK SmallTalks</a><br />
<a href="http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/MVC/Controller/Wire_Components">ZK Developer's Reference</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-619908529158146379.post-2608646491769588882012-03-12T13:52:00.001-07:002012-03-13T20:37:05.062-07:00The Little Man Computer<span style="font-family: 'Trebuchet MS', sans-serif;">The Little Man Computer presents a simplification of the modern computer architecture. This post will go through the LMC model and from there we'll infer what goes on inside the common computer when a program is executed. </span><br />
<br />
<h4 style="font-family: 'Trebuchet MS', sans-serif;">
A Hypothetical Task for LM</h4>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">We'll skip any formalities and deal with them later. </span><span style="font-family: 'Trebuchet MS', sans-serif;">Imagine if a little man, LM, is charged with the task of adding a given number x, </span><span style="font-family: 'Trebuchet MS', sans-serif;">no more than 3 digits,</span><span style="font-family: 'Trebuchet MS', sans-serif;"> to an arbitrary number, say 22, then add their sum </span><span style="font-family: 'Trebuchet MS', sans-serif;">to another given number y. </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">That is, performing x + 22 + y, where x and y are numbers we supply to LM. </span><br />
<br />
<br />
<h4 style="font-family: 'Trebuchet MS', sans-serif;">
Set up LM an Office</h4>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Let's imagine the setting that</span><span style="font-family: 'Trebuchet MS', sans-serif;"> must be provided to LM for him to do his job.</span><br />
<br />
<ol>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">he'll need a box to get the most recent number given from his user - an "<b>In Basket</b>"</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">since LM reads one instruction at a time, he needs a set of boxes to help him store data and instructions alike - "<b>100 Mailboxes</b>" labelled from 00 to 99</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">something to help him do the arithmetic - a "<b>Calculator</b>"</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">an indicator, which can be reset, to let LM know which mailbox to look for the next instruction or data - an "<b>Instruction Counter</b>"</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">a box that he could present the result to the user - an "<b>Out Basket</b>"</span></li>
</ol>
<br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">So we have an environment set up shown schematically like this:</span><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE9y7QJRSTOMukgwMEx3chNwEBjSRXgWWFV-0S_SLVI3Qei7AzWktKU-ZwHFncBKI3kCnv6bxZnrNuaLYlLtPPsq1Kj_eLJN19rEcDoLfVtvpnUmz6d_TPec3qF10bZVVIowJUWhLm5N0/s1600/LMC_env.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE9y7QJRSTOMukgwMEx3chNwEBjSRXgWWFV-0S_SLVI3Qei7AzWktKU-ZwHFncBKI3kCnv6bxZnrNuaLYlLtPPsq1Kj_eLJN19rEcDoLfVtvpnUmz6d_TPec3qF10bZVVIowJUWhLm5N0/s640/LMC_env.png" width="640" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<h4 style="font-family: 'Trebuchet MS', sans-serif;">
What to Instruct LM</h4>
<br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now we turn our attention to instructing LM to carry out the addition of numbers. The following is the steps that we wish him to follow:</span><br />
<br />
<ol>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">LM fetches the number </span><span style="font-family: 'Trebuchet MS', sans-serif;"><b style="font-style: italic;">x</b>, which we'd supply,</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and keys in </span><b style="font-family: 'Trebuchet MS', sans-serif;"><i>x</i></b><span style="font-family: 'Trebuchet MS', sans-serif;"> on the Calculator</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">fetch the arbitrary number 22 which we stored in a mailbox and add it to <b><i>x</i></b>; this is feasible since the value of <b><i>x</i></b> is still on the Calculator</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">LM stores the sum to a mailbox for later reference</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">we'd supply LM with another number, <b><i>y</i></b>, which LM keys in on the Calculator</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">LM retrieves the value of <i><b>x</b></i>+22 from the mailbox which he previously stored in step #4 and add it to <b><i>y</i></b> on the Calculator; note the value of <i><b>y</b></i> was already entered in step #5</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">LM puts the total sum of 3 number, <b><i>x</i></b>, <b><i>y</i></b>, and 22, to the Out Basket</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">LM can now go on a coffee break</span></li>
</ol>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Note that step #4 is needed since in step #5 LM would punch in the value of y hence erasing the sum of x + 22. Each instruction is placed in its respective mailbox and LM will rely on the Instruction Counter to know which mailbox to go to next. Let's review the above instructions schematically:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYH1vTiHOo674EZE_lnbCkKn6pcdwiX5NE3vY_yF4Ec6xnIaZ4OwkAMZAtMzAjISnv9E8gncDry9Oljhm0T7rCJ9cwQUWF6Xhfrka5MEQJCPnn2k90gYmJ2LGsyQHzPHKPS26LTLX07qM/s1600/LMC_proc.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYH1vTiHOo674EZE_lnbCkKn6pcdwiX5NE3vY_yF4Ec6xnIaZ4OwkAMZAtMzAjISnv9E8gncDry9Oljhm0T7rCJ9cwQUWF6Xhfrka5MEQJCPnn2k90gYmJ2LGsyQHzPHKPS26LTLX07qM/s640/LMC_proc.png" width="640" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<h4 style="font-family: 'Trebuchet MS', sans-serif;">
How to Instruct LM</h4>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">At this point, we know what instructions to give LM to do the job; here, we'll need to translate these steps into instructions that LM can understand.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">For our simple task here we'll only need a subset of the complete LMC instructions available. Note that different implementations of the LMC exist so the instruction set varies as well. The table below summarizes the instructions needed to tell our LM to do his job:</span><br />
<br />
<table border="0"><tbody>
<tr> <th><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Operation</span></th> <th><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Mnemonic</span></th> <th><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Machine Code</span></th></tr>
<tr> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Input</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">IN</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">901</span></div>
</td></tr>
<tr> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Output</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">OUT</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">902</span></div>
</td></tr>
<tr> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Add</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">ADD</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">1xx</span></div>
</td></tr>
<tr> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Store</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">STO</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">5xx</span></div>
</td></tr>
<tr> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Data</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">DAT</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">xxx</span></div>
</td></tr>
<tr><td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Coffee Break</span></div>
</td> <td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">COB</span></div>
</td><td><div style="text-align: center;">
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000</span></div>
</td></tr>
</tbody></table>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Note: The x's for Add and Store refer to the mailbox numbers. x's for Data is the actual data value we wish to store in the next available mailbox</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Machine code is understood by LM but tedious for people to memorize or write. So the operation codes (opcode) are expressed in mnemonics as shown in the table. We can now write the task instructions as follows: </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">IN </span><span style="font-family: 'Trebuchet MS', sans-serif;"> #copy the number x we supplied in In Basket onto the Calculator</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">ADD 07 #add the number, 22, which we stored in mailbox 7 to x</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">STO 08 #store the the result of x+22 to mailbox 8</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">IN #c</span><span style="font-family: 'Trebuchet MS', sans-serif;">opy the number y we supplied in In Basket onto the Calculator</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">ADD 08 #add the value we stored in mailbox 8 to the number y</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">OUT #copy the value of y from the Calculator to the Out Basket</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">COB #take a well deserved coffee break, ie. halt</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">DAT 22 #we place the arbitrary number 22 in the next available mailbox, </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"> #in this case, box 7 is available after all the instructions have taken up box 0 to 6</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<br />
<h4 style="font-family: 'Trebuchet MS', sans-serif;">
Give LMC a Test Run</h4>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now that we have an imagination of how the LMC works, let's give the instructions a run on a </span><a href="http://www.d.umn.edu/~gshute/cs3011/LMC.html#applet" style="font-family: 'Trebuchet MS', sans-serif;" target="_blank">LMC Simulator Applet</a><span style="font-family: 'Trebuchet MS', sans-serif;">, courtesy of University of Minnesota Duluth.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlsUOZC4Ov8XJnn3mMzPizxB3Qs2P9Y-oo1BT9bjKpEkhDvdtgCqAvinqNXSEtocEaJOiYts2q8NZft5MimteMFyhTrQpePk2ZmJqSlrStTLwDYzbal7DexwHvV6A9l7AogFxb-VwsOXY/s1600/LMC_simulator.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlsUOZC4Ov8XJnn3mMzPizxB3Qs2P9Y-oo1BT9bjKpEkhDvdtgCqAvinqNXSEtocEaJOiYts2q8NZft5MimteMFyhTrQpePk2ZmJqSlrStTLwDYzbal7DexwHvV6A9l7AogFxb-VwsOXY/s1600/LMC_simulator.png" /></a></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">We'll now give LMC a run:</span><br />
<ol>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">type in the mnemonic instructions in the </span><b style="font-family: 'Trebuchet MS', sans-serif;">LMC Editor</b></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">press the </span><b style="font-family: 'Trebuchet MS', sans-serif;">Assemble</b><span style="font-family: 'Trebuchet MS', sans-serif;"> button to generate the machine code in the <b>LMC Assembler</b> window</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">click the <b>Load</b> button in the <b>LMC Computer</b> window. Notice the machine code is displayed under the </span><b style="font-family: 'Trebuchet MS', sans-serif;">Memory</b><span style="font-family: 'Trebuchet MS', sans-serif;"> field</span><span style="font-family: 'Trebuchet MS', sans-serif;">. <b>Accumulator</b> refers to LM's calculator. </span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">click <b>Step </b></span><span style="font-family: 'Trebuchet MS', sans-serif;">to follow the execution of our instructions. Notice the arbitrary number 22 is stored in box 7 and the sum of 22 and the first input, in this case 133, is stored in box 8, which is coherent with our instructions given.</span></li>
</ol>
<br />
<h4 style="font-family: 'Trebuchet MS', sans-serif;">
Inference to the Common Computer Architecture</h4>
<br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">From the LMC model, we can take away some key points to help us to understand the common computer architecture (Von Neumann architecture).</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Let's first map the LMC terms to their corresponding parts in a common computer:</span></div>
<div>
<table border="0" cellpadding="2" cellspacing="2" style="background-color: white; width: 400px;"> <tbody>
<tr> <td><span style="background-color: white;">1. </span><span style="background-color: white; font-family: 'Trebuchet MS', sans-serif;">The Little Man</span></td><td><b><span style="font-family: Arial, Helvetica, sans-serif;">></span></b></td> <td><span style="font-family: 'Trebuchet MS', sans-serif;">The Control Unit</span></td> </tr>
<tr> <td><span style="font-family: 'Trebuchet MS', sans-serif;">2. Calculator / Accumulator</span></td> <td><span style="font-family: Arial, Helvetica, sans-serif;"><b>></b></span></td> <td><span style="font-family: 'Trebuchet MS', sans-serif;">Arithmetic Logic Unit</span></td> </tr>
<tr> <td><span style="font-family: 'Trebuchet MS', sans-serif;">3. Instruction Counter</span></td> <td><b style="font-family: Arial, Helvetica, sans-serif;">></b></td> <td><span style="font-family: 'Trebuchet MS', sans-serif;">Program Counter</span></td> </tr>
<tr> <td><span style="font-family: 'Trebuchet MS', sans-serif;">4. Mailboxes </span></td> <td><b style="font-family: Arial, Helvetica, sans-serif;">></b></td> <td><span style="font-family: 'Trebuchet MS', sans-serif;">Main Memory</span></td> </tr>
<tr> <td><span style="font-family: 'Trebuchet MS', sans-serif;">5. In Basket + Out Basket</span></td> <td><b style="font-family: Arial, Helvetica, sans-serif;">></b></td> <td><span style="font-family: 'Trebuchet MS', sans-serif;">I/O</span></td> </tr>
</tbody></table>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The common computer components have the same roles to their LMC counter parts. The Control Unit and the Arithmetic Logic Unit (ALU) together make up the CPU. A simplified schematic diagram of a common computer is as such:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFKRJzuLomUiSIZ4NUaGpQsJP_p7lhI6btc3Y3vjuLEpcd5uTBBfosfQoC4ssgKx6tKvTVZ0cOSBt8JIhHI7-HYou9oBwKwnr2Lf4wFFwWlVjHwsqNJwYwdMX6NXuu16AyTBG4c82Zic0/s1600/simplified_arch.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFKRJzuLomUiSIZ4NUaGpQsJP_p7lhI6btc3Y3vjuLEpcd5uTBBfosfQoC4ssgKx6tKvTVZ0cOSBt8JIhHI7-HYou9oBwKwnr2Lf4wFFwWlVjHwsqNJwYwdMX6NXuu16AyTBG4c82Zic0/s1600/simplified_arch.png" /></a></div>
<br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Under this architecture:</span></div>
<div>
<ol>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">both programs(instructions) and data are stored in memory</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">ALU holds data temporarily until calculation is carried out</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">program counter is incremented each time an instruction is fetched; the order of execution is sequential unless branching (we'll look into this in a post to follow) occurs</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Control Unit oversees the machine cycle: <b>Fetch</b>, <b>Decode</b>, and <b>Execute</b>. For instance, performing instruction 107 (mnemonic: ADD 07) stored in mailbox 01, upon reading the program counter for his next step to take, LM goes to mailbox 1 to retrieve the instruction 107, decoding <b>107</b> as <b>1</b> (the add operation) followed by the mailbox number <b>07</b></span><span style="font-family: 'Trebuchet MS', sans-serif;">, then execute the instruction (adding the data value stored in mailbox 7 to the value currently keyed in on the calculator).</span></li>
</ol>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">We've just tapped into the concepts of LMC and how it models the common computer we so heavily rely on everyday. In later posts, let's look at how to get LMC to do more interesting things using branching etc. </span></div>
</div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-619908529158146379.post-78638472139215394242012-03-12T13:52:00.000-07:002012-06-13T20:25:57.267-07:00Prologue<span style="font-family: 'Trebuchet MS', sans-serif;">This blog serves as a diary of my explorations, past or present, in technology.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Tech Dojo is made public so that ideas and techniques can be shared and validated among all who wish to participate. </span>Unknownnoreply@blogger.com1