From Documentation

Jump to: navigation, search




  • Author
    Tom M. Yeh and Henri Chen, Potix Corporation
  • Date
    March 22, 2007
  • Version


In this article, we'll introduce you the most exciting new additions to ZK 2.3.


Contents

New Scripting Languages

In addition to Java (by BeanShell), ZK supports JavaScript, Ruby (jRuby) and Groovy now.

By default, the scripting language is assumed to be Java. However, you can select different language by specifying the language attribute as follows. The language attribute is case insensitive.

<zscript language="javascript">
alert('Say Hi in JavaScript');
new Label("Hi, JavaScript!").setParent(win);
</zscript>

You can use several languages in the same page To specify the scripting language for an event handler, you can prefix with, say, javascript: as follows. Notice: don't put whitespace before or after the language name.

<button onClick="javascript: do_something_in_js();"/>

Moreover, you can change the default scripting language for a particual page with the page directive as follows.

<?page zscript-language="Ruby"?>
<window border="normal">
  <vbox id="vb">
    <label id="l" value="Hi"/>
    <button label="change label" onClick="$l.value='Hi, Ruby';"/>
    <button label="add label"
      onClick="(Java::Label.new 'New').parent = $vb"/>
  </vbox>
  <button label="alert" onClick="alert 'Hi, Ruby'"/>
</window>

If you want to add support for another language, refer to Teach ZK a New Language.

Client Side Action Reloaded

In 2.3, ZK introduced the so-called late-binding EL expressions to allow developers to pass not only components but also Java objects to the client-side JavaScript codes. Furthermore, many more animation effects are added.


Late-Binding EL Expressions

Before 2.3, ZK used to resolve every variable if it matches the name of a component. It is costly, error proning and not able to pass other Java objects, such as Date and numbers. Therefore, the late-binding EL expressions are introduced to help developers to reference Java objects more easily.

A late-binding EL expression is an EL expression that are evaluated as late as when the component is being rendered to HTML tags. The notation is #{expr}. For example,

<button action="onmouseover: action.show(#{parent.tip})"/>


On the other hand, if you assign an EL expression starting with ${, it will be evaluated at the Component Creation Phase, before assigning to the action property. For example,

<button action="onfocus: action.show(${tip}); onblur: action.hide(${tip})"/>
<div id="tip" visible="false">...</div>


will be evaluated to

<button action="onfocus: action.show(); onblur: action.hide()"/>
<div id="tip" visible="false">...</div>

since the tip component is not created when assigning the action property.


New Visual Effects

A client-side object called anima is added to support more visual effects. Notice: anima is implemented by use of Scriptaculous, so it shares a limitation that the HTML output of a component must be enclosed with HTML DIV tag. Not all ZUL components are designed in this way. If any doubt, you can use the div component as the parent of the component you want to add animation effects.

<window title="Animation Effects">
  <style>
.ctl {
  border: 1px outset #777; background:#ddeecc;
  margin: 2px; margin-right: 10px; padding-left: 2px; padding-right: 2px; 
}
  </style>

  <label value="Slide" sclass="ctl"
action="onmouseover: anima.slideDown(#{t}); onmouseout: anima.slideUp(#{t})"/>
  <label value="Fade" sclass="ctl"
action="onmouseover: anima.appear(#{t}); onmouseout: anima.fade(#{t})"/>
  <label value="Puff" sclass="ctl"
action="onmouseover: anima.appear(#{t}); onmouseout: anima.puff(#{t})"/>
  <label value="Drop Out" sclass="ctl"
action="onmouseover: anima.appear(#{t}); onmouseout: anima.dropOut(#{t})"/>

  <div id="t" visible="false">
	<div>
	<groupbox>
	  <caption label="Dynamic Content"/>
	  Content to show and hide dynamically.
	  <datebox/>
	</groupbox>
	Description <textbox/>
	</div>
  </div>
</window>


The onshow and onhide Actions

In addition to events that browsers support, ZK 2.3 adds the support of two special events, onshow and onhide. They allow developers to control the visual effect to show or to hide a component.

<zk>
  <window id="win" border="normal" width="200px" sizable="true" mode="overlapped"
action="onshow:anima.appear(#{self});onhide:anima.fade(#{self})" visible="false">
	<caption image="/img/inet.png" label="Hi there!"/>
	<checkbox label="Hello, Wolrd!"/>
	<button label="close" onClick="win.visible = false"/>
  </window>
  <button label="Overlap" onClick="win.doOverlapped();"/>
  <button label="Toggle Visible" onClick="win.visible = !win.visible"/>
</zk>


Macro Components Reloaded

Inline Macro Expansion

By default, a macro component (implementing org.zkoss.zk.ui.ext.Macro) is created when ZK Loader is interpreting the ZUML page. The macro component encapuslates the implementation, and allows component developers to provide a unique API.

However, the macro component cannot be used in a layout that expecting certain components. For example, the following codes will fail since ua is a macro component that is independent of whatever the template is.

<?component name="username" macrouri="username.zul"?>
<grid>
  <rows>
	<username id="ua" name="John"/>
  </rows>
</grid>


ZK 2.3 introduces a new kind of macros called inline macros. They are expanded inline at the place they are used. In other words, it works as if you type the content of the inline macro directly to the target page.

For example, assume the content of username.zul as follows.

<row>
Username <textbox id="" value=""/>
</row>


Then, you can add an attribute called inline to the component directive as follows.

<?component name="username" macrouri="username.zul" inline="true"?>
<grid>
  <rows>
	<username id="ua" name="John"/>
  </rows>
</grid>


The result will be as follows.

<grid>
  <rows>
<row>
Username <textbox id="ua" value="John"/>
</row>
  </rows>
</grid>


Change the Macro Template after Created

ZK 2.3 allows developers to change the macro template for a particual instance by calling the setMacroURI method. Once URI is changed, the macro component is re-created.

<?component name="hello" macro-uri="/userguide/misc/includedHello.zul"?>
<window title="Macro Demo" border="normal" width="300px">
  <hello id="h"/>
  <button label="change" onClick="h.setMacroURI("/test/menu.zul")"/>
</window>

Notice that inline macros don't support this feature, since there is no real component is associated with it.


Components Reloaded

Live Grid

Grid supports the live data. Developers need only to specify an instance of org.zkoss.zul.ListModel to the mode property. Refer to How to realize the idea of live data in a Grid for more information.

Upload Multiple Files at the Same Time

To upload multiple files, developers can simply specify the maximal allowed number of files to upload at once as follows.

Media[] media = Fileupload.get(5);
if (media != null) {
  //handle them. Note: depending on how many files an user really uploaded
  //media.length is not necessary to be 5
}


The variables Element

Like assigning the custom attributes, you can assign variables to the current namespace by use of the variables element as follows.

<variables rich="simple" simple="${intuitive}"/>


New Way to Customize the Look of Windows

The window component allows developers to customize the content, the title and the whole component separately.

For example, if you want to create a window with scrollbars and dash borders, just specify a style class as follows.

<zk>
  <style>
  div.wc-embedded-dash {
	padding: 2px; border: 3px dashed #aab;
  }
  </style>
  <window title="My Window" border="dash" width="200px">
  Hello, World!
  </window>
</zk>


where wc-embedded-dash defines the style of the inner box of the window. The style class is named by concatenating wc, the sclass property and the border property together and separating them with dash (-).


Free Layout of the Radio Group and Buttons

You can mix radiogroup and radio

<radiogroup>
 <grid>
  <rows>
   <row><radio label="Apple" selected="true"/> Fruit, music or computer</row>
   <row><radio label="Orange"/><textbox/></row>
   <row><radio label="Banana"/><datebox/></row>
  </rows>
 </grid>
</radiogroup>

The radio button belongs to the nearest ancestor radiogroup. You can even nest one radiogroup to another. Each of them operate independently, though there might be some sort of visual overlap.


Customizing Progressing Prompts, Error Boxes, and More

ZK Client Engine provides several 'hook' to let developers customize the look and feel.

For example, you can display the progressing prompt different by the following codes.

<script type="text/javascript">
function Boot_progressbox(id, msg, x, y) {
  var html = '<div id="'+id+'" style="left:'+x+'px;top:'+y+'px;'
   +'position:absolute;z-index:79000;background-color:#FFF0C8;'
   +'white-space:nowrap;border:1px solid #77a;padding:6px;">'
   +msg+'</div>';

  document.body.insertAdjacentHTML("afterbegin", html);
  return $e(id);
}
</script>

Similarly, you can override Validate_errorbox to have a custom error box, Comboitem_bgcolor for the background color of the comboitem, and Selectable_bgcolor for the background color of the list item and tree item.


Data Binding Reloaded

Data Binding with Live Grid

You can use collection data binding with live Grid now.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?> 
<window id="mainwin" xmlns:a="http://www.zkoss.org/2005/zk/annotation">
  <a:bind model="personList"/>
  <grid width="600px" height="200px">
	<rows>
	  <a:bind _var="person"/>
	  <row>
		  <a:bind value="person.firstName"/>
		  <textbox id="fn"/>

		  <a:bind value="person.lastName"/>
		  <textbox id="ln"/>

		  <a:bind value="person.fullName"/>
		  <label maxlength="20"/>
	  </row>
	</rows>
  </grid> 
  
  <zscript>
  public class Person {
	String _firstName;
	String _lastName;
	
	public void setFirstName(String f) {
	  _firstName = f;
	}
	public String getFirstName() {
	  return _firstName;
	}
	public void setLastName(String l) {
	  _lastName = l;
	}
	public String getLastName() {
	  return _lastName;
	}
	public String getFullName() {
	  return _firstName+" "+_lastName;
	}
  }
  
  //prepare collection list
  setupPerson(Person person, int j) {
	person.setFirstName("First"+j);
	person.setLastName("Last"+j);
  }
  
  //prepare the example person List
  int count = 30;
  List personList = new ArrayList();

  for(int j= 0; j < count; ++j) {
	Person personx = new Person();
	setupPerson(personx, j);
	personList.add(personx);
  }
  </zscript>
</window>

You can data binding the Grid live model directly to a List, Set, Map, or Object array automatically and no need to write a specific RowRenderer to handle multi-column rendering. The new ZK AnnotateDataBinder handles it all, with zero codes.


Listbox and Grid with the enum Type

You can even data binding the Listbox and Grid live model directly to a enum Type now. Given the enum class and all defined enums are automatically retrieved and displayed.

//Season.java
public enum Season { WINTER, SPRING, SUMMER, FALL };
  
//season.zul
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?> 
<zk xmlns:a="http://www.zkoss.org/2005/zk/annotation">
  <zscript>Class seasonClass = Season.class;</zscript>
  <a:bind model="seasonClass"/>
  <listbox mold="select" rows="1"/>
</zk>


Or maybe you want to show all enums through the enum's static values() method:

//season2.zul
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?> 
<zk xmlns:a="http://www.zkoss.org/2005/zk/annotation">
  <zscript>Object[] seasons = Season.values();</zscript>
  <a:bind model="seasons"/>
  <listbox mold="select" rows="1"/>
</zk>


The above two ways are both supported and works seamlessly.




Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.
You got stuck here?
Let us know how we can improve this page
For specific questions please use the forum