Widget Customization"

From Documentation
m
 
(24 intermediate revisions by 5 users not shown)
Line 3: Line 3:
 
=Override Widget's Default Behavior=
 
=Override Widget's Default Behavior=
  
There are many ways to override the default behavior of widgets and even ZK Client Engine. JavaScript is a dynamic language and you could override almost any method you want.
+
There are many ways to override the default behavior of widgets or even ZK Client Engine. JavaScript is a dynamic language and you could override almost any methods you want.
  
 
==Override a Widget Method==
 
==Override a Widget Method==
 
+
This way overrides a particular widget. So, it only overrides the widget's methods you specified and does not affect other widgets on the same page.
For example, suppose we want to change the CSS style of a label when its value is changed, then we might have the code as follows.
+
For example, suppose you want to change a label's CSS style when its value is changed, then you can write the code as follows:
  
 
<source lang="xml">
 
<source lang="xml">
<window xmlns:w="http://www.zkoss.org/2005/zk/client">
+
<zk xmlns:w="http://www.zkoss.org/2005/zk/client">
 
       <label>
 
       <label>
 
             <attribute w:name="setValue">
 
             <attribute w:name="setValue">
Line 22: Line 22:
 
             </attribute>
 
             </attribute>
 
       </label>
 
       </label>
</window>
+
</zk>
 
</source>
 
</source>
  
 
where
 
where
  
* We specify [[ZUML Reference/ZUML/Namespaces/Client|client namespace]] to the <code>setValue</code> attribute to indicate it is the method to override
+
* We specify [[ZUML Reference/ZUML/Namespaces/Client|client namespace]] to the <code>setValue</code> attribute to indicate the method to override
 
* The content of the attribute is a complete function definition of the method, including <code>function ()</code>
 
* The content of the attribute is a complete function definition of the method, including <code>function ()</code>
 
* You can access the widget by <code>this</code> in the function
 
* You can access the widget by <code>this</code> in the function
 
* You can access the original method by <code>this.$xxx</code>, where xxx is the method name being overridden. If the method doesn't exist, it is null.
 
* You can access the original method by <code>this.$xxx</code>, where xxx is the method name being overridden. If the method doesn't exist, it is null.
 
* To retrieve another widget, use <code>this.$f('anotherWidgetId')</code> or other methods as described in the previous section
 
* To retrieve another widget, use <code>this.$f('anotherWidgetId')</code> or other methods as described in the previous section
* You can specify EL expressions<ref>EL expressions are allowed since ZK 5.0.2</ref> in the content of the attribute, such as
+
* {{versionSince| 5.0.2}} You can specify EL expressions in the content of the attribute, such as
  
<source lang="javascript">
+
<source lang="xml">
w:setValue='function (value) { this.$setValue(value + "${whatever}")}';
+
<label w:setValue='function (value) { this.$setValue(value + "${whatever}")}' />
 
</source>
 
</source>
  
Notice EL expressions are evaluated at the server before sent back to the client. Thus, you could any Java class or variables in EL expressions.
+
Notice that EL expressions are evaluated at the server-side before sending back to the client. Thus, you can use any Java class or variables in EL expressions.
  
<blockquote>
+
== Override a Widget in Java ==
----
 
<references/>
 
</blockquote>
 
  
==Override a Default Widget Method==
+
In addition to ZUML, you can override a Widget's '''method''' or '''field''' by the use of <javadoc method="setWidgetOverride(java.lang.String, java.lang.String)" type="interface">org.zkoss.zk.ui.Component</javadoc> at the server. For example,
  
In previous section, we showed how to override method of a particular widget we declared. However, it only affects the behavior of a particular instance. If you want to modify the behavior of all instances of a widget class, you have to override the method in <code>prototype</code><ref>For more information about JavaScript's prototype, please refer to [http://www.packtpub.com/article/using-prototype-property-in-javascript Using Prototype Property in JavaScript] and [http://www.w3schools.com/jsref/jsref_prototype_math.asp JavaScript prototype Property]</ref>.
+
<source lang="java">
 +
myLabel.setWidgetOverride("setValue",
 +
    "function (value) {this.$setValue('overloaded setValue');}");
 +
</source>
 +
 
 +
==Override a Default Widget Method in zul==
 +
 
 +
In the previous section, we showed you how to override the method of a particular widget. If you want to modify the behavior of all instances of a widget class, you have to override the method in <code>prototype</code> (For more information about JavaScript's prototype, please refer to [http://www.packtpub.com/article/using-prototype-property-in-javascript Using Prototype Property in JavaScript] and [http://www.w3schools.com/jsref/jsref_prototype_math.asp JavaScript prototype Property]).
  
 
For example,
 
For example,
  
<source lang="xml" high="5">
+
<source lang="xml" highlight="5">
 
<window xmlns:w="http://www.zkoss.org/2005/zk/client">
 
<window xmlns:w="http://www.zkoss.org/2005/zk/client">
 
<label id="labelone" value="label one"/>
 
<label id="labelone" value="label one"/>
Line 67: Line 71:
 
</source>
 
</source>
  
where we assign a new method to <code>zul.wgt.Label.prototype.setValue</code>. Since it is <code>prototype</code>, the setValue method of all instances are modified.
+
Where we assign a new method to <code>zul.wgt.Label.prototype.setValue</code>. Since it is <code>prototype</code>, the <code>setValue()</code> of all instances are overriden.
 +
 
 +
== Override a Default Widget Method in JavaScript File ==
 +
It's easy to include an overridden js in multiple zul files. Here is a sample:
 +
<source lang='js'>
 +
zk.afterLoad('zul.inp', function() { //specify zk widget package name
 +
    var exWidget = {};
 +
    zk.override(zul.inp.ComboWidget.prototype, exWidget, { //specify zk full widget name
 +
doClick_: function(e){
 +
exWidget.doClick_.apply(this, arguments); //call the original widget's overridden function
 +
//implement your custom logic
 +
},
 +
    });
 +
 
 +
});
 +
</source>
 +
* Line 1: this line will run <code>zk.override()</code> after the <code>zul.inp</code> widgets are loaded, so you don't need to take care this overridden script's loading order. You can include such JavaScript in any place of a zul.
 +
 
  
<blockquote>
 
----
 
<references/>
 
</blockquote>
 
  
 
==Override a Widget Field==
 
==Override a Widget Field==
  
You can override a method or a field no matter it exists or not. For example, it is easy to pass the application-specific data to the client, such as
+
You can override a method or a field no matter it exists or not. For example, you can use this feature to pass an application-specific data to a widget, such as
  
<source lang="javascript">
+
<source lang="xml">
<label value="hello" w:myval="'${param.foo}'"/>
+
<label value="hello" w:myOption="'${param.enabled}'"/>
 
</source>
 
</source>
  
 
Notice that the content of the attribute must be a valid JavaScript snippet. To specify a string (as shown above), you have to enclose it with ' or " if you want to pass a string. It also means you can pass anything, such as <code>new Date()</code>.
 
Notice that the content of the attribute must be a valid JavaScript snippet. To specify a string (as shown above), you have to enclose it with ' or " if you want to pass a string. It also means you can pass anything, such as <code>new Date()</code>.
 
==== Override a Widget Method in Java ====
 
 
In additions to ZUML, you could override a Widget method or field by use of <javadoc method="setWidgetMethod(java.lang.String, java.lang.String)" type="interface">org.zkoss.zk.ui.Component</javadoc> at the server. For example,
 
 
<source lang="java">
 
label.setWidgetOverride("setValue",
 
    "function (value) {this.$setValue('overloaded setValue');}");
 
</source>
 
  
 
=Specify Your Own Widget Class=
 
=Specify Your Own Widget Class=
Line 107: Line 115:
  
 
<source lang="javascript">
 
<source lang="javascript">
 +
zk.$package("foo");
 
zk.afterLoad("zul.wgt", function () {
 
zk.afterLoad("zul.wgt", function () {
   zk.$package("foo").MyButton = zk.$extends(zul.wgt.Button, {
+
   foo.MyButton = zk.$extends(zul.wgt.Button, {
 
     setLabel: function (label) {
 
     setLabel: function (label) {
 
       this.$supers("setLabel", arguments);
 
       this.$supers("setLabel", arguments);
Line 119: Line 128:
 
Notice that <javadoc directory="jsdoc" method="afterLoad(_global_.String, _global_.Function)">_global_.zk</javadoc> is used to defer the declaration of <code>foo.MyButton</code> until <code>zul.wgt</code> has been loaded.
 
Notice that <javadoc directory="jsdoc" method="afterLoad(_global_.String, _global_.Function)">_global_.zk</javadoc> is used to defer the declaration of <code>foo.MyButton</code> until <code>zul.wgt</code> has been loaded.
  
==Load Additional JavaScript Files==
+
=Load JavaScript Files for Overriding Widgets=
 +
 
 +
If you put your overridden js code in a separate file, you need to include it to take effect on widgets.
  
You could use <javadoc>org.zkoss.zul.Script</javadoc>, HTML SCRIPT tag or [[ZUML Reference/ZUML/Processing Instructions/script|script]] to load additional JavaScript files. Please refer to [[ZK_Component_Reference/Essential_Components/Script|script]] for more information.
+
== Page Scope==
 +
If you just want to override widgets on some pages, you can use one of the following:
 +
* [[ZK_Component_Reference/Essential_Components/Script|<script> component]]
 +
* HTML <code><script></code>
 +
* [[ZUML Reference/ZUML/Processing Instructions/script|<?script ?> directive]]
 +
 
 +
== Application Scope ==
 +
To override all widgets in the whole application, you need to include the js file in every page with:
 +
* [[ZK%20Configuration%20Reference/zk.xml/The%20device-config%20Element/The%20embed%20Element | <embed> in zk.xml]]
 +
* [[ZK_Client-side_Reference/Language_Definition/javascript]]
  
 
= The Client-Attribute Namespace =
 
= The Client-Attribute Namespace =
  
[since 5.0.3]
+
{{versionSince| 5.0.3}}
  
The [[ZUML Reference/ZUML/Namespaces/Client Attribute|client-attribute namespace (<nowiki>http://www.zkoss.org/2005/zk/client/attribute</nowiki>; shortcut, <code>client/attribute</code>) is used to specify additional DOM attributes that are not generated by widgets. In other words, whatever attributes you specify with the client-attribute namespace will be generated directly to the browser's DOM tree. Whether it is meaningful, it is really up to the browser -- ZK does not handle or filter it at all.
+
You can specify additional '''DOM attributes''' that are not generated by ZK widgets with [[ZUML Reference/ZUML/Namespaces/Client Attribute|client-attribute namespace]] (<code>http://www.zkoss.org/2005/zk/client/attribute</code>. shortcut, <code>client/attribute</code>). In other words, whatever attributes you specify with the client-attribute namespace will be generated directly to the browser's DOM tree. Whether it is meaningful, it is really up to the browser -- ZK does not handle or filter it at all.
  
For example, you want to listen to the <code>onload</code> event, and then you can do as follows<ref>Fore more information, please refer to [[ZK Component Reference/Essential Components/Iframe#onload|ZK Component Reference: iframe]]</ref>.
+
For example, you want to listen to the <code>onload</code> event, and then you can do as follows. Fore more information, please refer to [[ZK Component Reference/Essential Components/Iframe#onload|ZK Component Reference: iframe]].
  
 
<source lang="xml">
 
<source lang="xml">
Line 136: Line 156:
 
</source>
 
</source>
  
If the attribute contains colon or other special characters, you can use the <code>attribute</code> element as follows.
+
<syntaxhighlight lang='xml'>
 +
<zk xmlns:ca="client/attribute">
 +
    HTML 5 spell check enabled:
 +
    <textbox ca:spellcheck="true"/>
 +
</zk>
 +
</syntaxhighlight>
 +
 
 +
If the attribute contains colon or other special characters, you can use the <code>attribute</code> element as follows:
  
 
<source lang="xml">
 
<source lang="xml">
<div xmlns:ca="http://www.zkoss.org/2005/zk/client/attribute">
+
<div xmlns:ca="client/attribute">
 
   <attribute ca:name="ns:whatever">
 
   <attribute ca:name="ns:whatever">
 
   whatever_value_you_want
 
   whatever_value_you_want
Line 147: Line 174:
  
 
The other use of the client-attribute namespace is to specify attributes that are available only to certain browsers, such as accessibility and [http://www.section508.gov/index.cfm?FuseAction=Content&ID=12#Web Section 508].
 
The other use of the client-attribute namespace is to specify attributes that are available only to certain browsers, such as accessibility and [http://www.section508.gov/index.cfm?FuseAction=Content&ID=12#Web Section 508].
 
<blockquote>
 
----
 
<references/>
 
</blockquote>
 
  
 
=Version History=
 
=Version History=

Latest revision as of 06:51, 13 April 2022


Widget Customization



Override Widget's Default Behavior

There are many ways to override the default behavior of widgets or even ZK Client Engine. JavaScript is a dynamic language and you could override almost any methods you want.

Override a Widget Method

This way overrides a particular widget. So, it only overrides the widget's methods you specified and does not affect other widgets on the same page. For example, suppose you want to change a label's CSS style when its value is changed, then you can write the code as follows:

<zk xmlns:w="http://www.zkoss.org/2005/zk/client">
      <label>
            <attribute w:name="setValue">
            function (value) {
                  this.$setValue(value); //call the original method
                  if (this.desktop) {
                        this._flag = !this._flag;
                        this.setStyle('background:'+(this._flag ? 'red':'green'));
                  }
            }
            </attribute>
      </label>
</zk>

where

  • We specify client namespace to the setValue attribute to indicate the method to override
  • The content of the attribute is a complete function definition of the method, including function ()
  • You can access the widget by this in the function
  • You can access the original method by this.$xxx, where xxx is the method name being overridden. If the method doesn't exist, it is null.
  • To retrieve another widget, use this.$f('anotherWidgetId') or other methods as described in the previous section
  • Since 5.0.2 You can specify EL expressions in the content of the attribute, such as
<label w:setValue='function (value) { this.$setValue(value + "${whatever}")}' />

Notice that EL expressions are evaluated at the server-side before sending back to the client. Thus, you can use any Java class or variables in EL expressions.

Override a Widget in Java

In addition to ZUML, you can override a Widget's method or field by the use of Component.setWidgetOverride(String, String) at the server. For example,

myLabel.setWidgetOverride("setValue",
    "function (value) {this.$setValue('overloaded setValue');}");

Override a Default Widget Method in zul

In the previous section, we showed you how to override the method of a particular widget. If you want to modify the behavior of all instances of a widget class, you have to override the method in prototype (For more information about JavaScript's prototype, please refer to Using Prototype Property in JavaScript and JavaScript prototype Property).

For example,

<window xmlns:w="http://www.zkoss.org/2005/zk/client">
	<label id="labelone" value="label one"/>
	<label id="labeltwo" value="label two"/>
	<script defer="true">
		var oldSV = zul.wgt.Label.prototype.setValue;
		zul.wgt.Label.prototype.setValue = function (){
			arguments[0]="modified prototype"+arguments[0];
			oldSV.apply(this, arguments);
		}					
	</script>
	<button label="change" onClick="labelone.setValue((new Date()).toString());
    labeltwo.setValue((new Date()).toString());"/>
</window>

Where we assign a new method to zul.wgt.Label.prototype.setValue. Since it is prototype, the setValue() of all instances are overriden.

Override a Default Widget Method in JavaScript File

It's easy to include an overridden js in multiple zul files. Here is a sample:

zk.afterLoad('zul.inp', function() { //specify zk widget package name
    var exWidget = {};
    zk.override(zul.inp.ComboWidget.prototype, exWidget, { //specify zk full widget name
		doClick_: function(e){
			exWidget.doClick_.apply(this, arguments); //call the original widget's overridden function
			//implement your custom logic
		},
    });

});
  • Line 1: this line will run zk.override() after the zul.inp widgets are loaded, so you don't need to take care this overridden script's loading order. You can include such JavaScript in any place of a zul.


Override a Widget Field

You can override a method or a field no matter it exists or not. For example, you can use this feature to pass an application-specific data to a widget, such as

<label value="hello" w:myOption="'${param.enabled}'"/>

Notice that the content of the attribute must be a valid JavaScript snippet. To specify a string (as shown above), you have to enclose it with ' or " if you want to pass a string. It also means you can pass anything, such as new Date().

Specify Your Own Widget Class

You could specify your own implementation instead of the default widget class (at the client) as follows.

<zk xmlns:w="http://www.zkoss.org/2005/zk/client">
  ...
  <button w:use="foo.MyButton"/>
</zk>

where foo.MyButton is a widget you implement. For example,

zk.$package("foo");
zk.afterLoad("zul.wgt", function () {
  foo.MyButton = zk.$extends(zul.wgt.Button, {
    setLabel: function (label) {
      this.$supers("setLabel", arguments);
     //do whatever you want
    }
  });
});

Notice that zk.afterLoad(String, Function) is used to defer the declaration of foo.MyButton until zul.wgt has been loaded.

Load JavaScript Files for Overriding Widgets

If you put your overridden js code in a separate file, you need to include it to take effect on widgets.

Page Scope

If you just want to override widgets on some pages, you can use one of the following:

Application Scope

To override all widgets in the whole application, you need to include the js file in every page with:

The Client-Attribute Namespace

Since 5.0.3

You can specify additional DOM attributes that are not generated by ZK widgets with client-attribute namespace (http://www.zkoss.org/2005/zk/client/attribute. shortcut, client/attribute). In other words, whatever attributes you specify with the client-attribute namespace will be generated directly to the browser's DOM tree. Whether it is meaningful, it is really up to the browser -- ZK does not handle or filter it at all.

For example, you want to listen to the onload event, and then you can do as follows. Fore more information, please refer to ZK Component Reference: iframe.

<iframe src="http://www.google.com" width="100%" height="300px"
  xmlns:ca="client/attribute" ca:onload="do_whater_you_want()"/>
<zk xmlns:ca="client/attribute">
    HTML 5 spell check enabled:
    <textbox ca:spellcheck="true"/>
</zk>

If the attribute contains colon or other special characters, you can use the attribute element as follows:

<div xmlns:ca="client/attribute">
  <attribute ca:name="ns:whatever">
  whatever_value_you_want
  </attribute>
</div>

The other use of the client-attribute namespace is to specify attributes that are available only to certain browsers, such as accessibility and Section 508.

Version History

Last Update : 2022/04/13


Version Date Content
     



Last Update : 2022/04/13

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.