Introduction
This is the second article of ZK CDT (ZK Component Development Tutorial) walkthrough, this article describe how to add attributes to a component then initiate component with attributes and/or dynamically update them.
The goal of this walkthrough is to create a quicknote component that help you do some quick note on web page (similar to you crop some screenshot, highlight something and add some text in photo editor), and describe each part of a component through each article in this walkthrough.
This is the second part: Handle attributes of a component
Result
View demo online:
http://screencast.com/t/UOlhr4E36i
Similer to the mask component in previous article, but now you can change the opacity and background-color of mask as needed.
Pre-request
ZK CDT: Create Custom Mask Component
http://ben-bai.blogspot.tw/2013/06/zk-cdt-create-custom-mask-component.html
Program
enhancedmask.zul
Contains an enhancedmask component, a slider/colorbox that control the opacity/background-color of the enhancedmask.
<zk>
<hlayout>
<!-- The enhancedmask component that will cover
its children by a mask -->
<enhancedmask width="500px" id="emask"
opacity="20" maskColor="#00FF00">
<button label="ZK Website" />
<iframe width="100%"
height="1000px"
src="http://www.zkoss.org/"></iframe>
</enhancedmask>
<div>
<!-- slider used to control opacity of enhancedmask -->
<slider curpos="20" maxpos="100">
<attribute name="onScroll"><![CDATA[
emask.setOpacity(((ScrollEvent)event).getPos());
]]></attribute>
<attribute name="onScrolling"><![CDATA[
emask.setOpacity(((ScrollEvent)event).getPos());
]]></attribute>
</slider>
<!-- colorbox used to control mask color of enhancedmask -->
<colorbox color="#00FF00">
<attribute name="onChange"><![CDATA[
emask.setMaskColor(self.getValue());
]]></attribute>
</colorbox>
</div>
</hlayout>
</zk>
EnhancedMask.java
The java class of enhancedmask comopnent, extends XulElement and add attributes opacity and maskColor.
package custom.zk.components.quicknote;
import org.zkoss.zul.impl.XulElement;
/**
* java class for EnhancedMask component,
* extends XulElement and add attributes opacity and maskColor
*
* Two new things:
*
* smartUpdate: used to update client side attribute with the UI thread,
* call it within ZK UI thread then it will bring the status
* back to client side
*
* renderProperties: used to render all properties to client side at the beginning,
* it is a part of component life cycle in ZK,
* will be called by ZK framework automatically.
*
* @author benbai123
*
*/
public class EnhancedMask extends XulElement {
private static final long serialVersionUID = -2084534449227910442L;
private int _opacity = 35;
private String _maskColor = "#ccc";
public void setOpacity (int opacity) {
// no negative
if (opacity < 0) {
opacity = 0;
}
// cannot larger than 100
if (opacity > 100) {
opacity = 100;
}
// update if value is changed
if (_opacity != opacity) {
_opacity = opacity;
smartUpdate("opacity", _opacity);
}
}
public int getOpacity () {
return _opacity;
}
public void setMaskColor (String maskColor) {
// update if there is a different value
if (maskColor != null // no null
&& !maskColor.isEmpty() // no empty
&& !maskColor.equals(_maskColor)) { // value is changed
_maskColor = maskColor;
smartUpdate("maskColor", _maskColor);
}
}
public String getMaskColor () {
return _maskColor;
}
//-- ComponentCtrl --//
// the renderProperties method is a part of component life cycle in ZK,
// it will be called by ZK framework automatically,
// remember to render super's properties first
protected void renderProperties(org.zkoss.zk.ui.sys.ContentRenderer renderer)
throws java.io.IOException {
super.renderProperties(renderer);
if (_opacity != 35) {
// this will call setOpacity (opacity) in widget class at client side
render(renderer, "opacity", _opacity);
}
if (!"#ccc".equals(_maskColor)) {
// this will call setMaskColor (maskColor) in widget class at client side
render(renderer, "maskColor", _maskColor);
}
}
}
EnhancedMask.js
The widget class of enhancedmask component, provide zclass and setters of opacity/maskColor.
/**
* Widget class of EnhancedMask component,
* extends zul.Widget, change zclass and add setters for
* attributes opacity and maskColor
*
* Two new things:
* setters: the setSomething methods are mapping to 'something' at
* server side when render or smartUpdate is called.
* e.g., setOpacity (in widget class) is called if executes
* smartUpdate("opacity", _opacity);
* or
* render(renderer, "opacity", _opacity);
* at server side
*
* $n(): This is the API to get dom elements by specified id.
* ZK will assign each component an ID (say uuid) (is unique within an ID Space),
* we usually assign the uuid to root dom element,
* and assign uuid+'-'+suffix to child elements
*
* In this case, this api will return the root element when you call this.$n(),
* and return the child element with specific suffix when you call this.$n(suffix)
*
* e.g., We specified uuid+'-mask' as the ID of child mask element in enhancedMask.js,
* so we can get the mask dom element by this.$n('mask');
*
*
* NOTE: It is important to specify the uuid to root dom element of a widget,
* or ZK can not find it while detaching it,
* i.e., will leave the element in dom tree after the component is detached,
* and causes weird bug or memory leak in browser.
*
* In most cases, you can call this.domAttrs_() directly when you output the html
* of root dom element then it should work fine.
*
*/
custom.zk.components.quicknote.EnhancedMask = zk.$extends(zul.Widget, {
/**
* default values: set default value in both java class and
* widget class, so do not need transfer them via network if
* we just want to use the default values
*/
_opacity: 35,
_maskColor: '#ccc',
setOpacity: function (opacity) {
// update if value is changed
if (this._opacity != opacity) {
// update value
this._opacity = opacity;
// try to get mask element
var mask = this.$n('mask');
if (mask) {
// apply opacity to mask if it is available
jq(mask).css('opacity', (opacity/100));
}
}
},
setMaskColor: function (maskColor) {
// update if value is changed
if (this._maskColor != maskColor) {
// update value
this._maskColor = maskColor;
// try to get mask element
var mask = this.$n('mask');
if (mask) {
// apply background-color to mask if it is available
jq(mask).css('background-color', maskColor);
}
}
},
// override with new css class name
getZclass: function () {
var zcls = this._zclass;
return zcls? zcls : 'z-enhancedmask';
}
});
enhancedMask.js
Define the redraw function that output the html code of enhancedmask component.
/**
* redraw for enhancedmask component,
* wrap children with a div then cover them,
* also generate style based on attributes
*/
function (out) {
var uuid = this.uuid,
zcls = this.getZclass(),
style = ' style="background-color: ' + this._maskColor
+'; opacity:' + (this._opacity/100) + ';"';
// output root dom element of this widget
out.push('<div', this.domAttrs_(), '>');
// output children
for (var w = this.firstChild; w; w = w.nextSibling)
w.redraw(out);
// output mask that cover children
// with generated style
out.push('<div id="', uuid, '-mask"', style, ' class="', zcls,'-cover"></div>');
out.push('</div>');
}
enhancedMask.css.dsp
Define the style of the dom elements in enhancedmask component.
<%--// ------------------------------------------- --%>
<%--// --%>
<%--// EnhancedMask component --%>
<%--// --%>
<%--// ------------------------------------------- --%>
<%--// root element --%>
.z-enhancedmask {
<%--// be the anchor of absolute positioned children --%>
position: relative;
overflow: hidden;
}
<%--// the mask that cover whole element --%>
<%--// no background-color and opacity specified --%>
<%--// since we specified them in widget class --%>
.z-enhancedmask-cover {
<%--// absoluted positioned --%>
position: absolute;
<%--// align the left-top corner of parent (root) element --%>
left: 0px;
top: 0px;
<%--// cover whole root element --%>
height: 100%;
width: 100%;
<%--// make it the top most element under root element --%>
z-index: 99999;
}
zk.wpd
Define components under "custom.zk.components.quicknote"
* only the added part, not the full code
NOTE: more components will be added with other articles later
...
<widget name="EnhancedMask" />
...
lang-addon.xml
Define all components in the project
* only the added part, not the full code
NOTE: more components will be added with other articles later
...
<!-- the second, enhancedmask component
can dynamically change the opacity and
background-color of mask
-->
<component>
<component-name>enhancedmask</component-name>
<component-class>custom.zk.components.quicknote.EnhancedMask</component-class>
<widget-class>custom.zk.components.quicknote.EnhancedMask</widget-class>
<mold>
<mold-name>default</mold-name>
<mold-uri>mold/enhancedMask.js</mold-uri>
<css-uri>css/enhancedMask.css.dsp</css-uri>
</mold>
</component>
...
Download
Full project at github
https://github.com/benbai123/ZK_Practice/tree/master/Components/projects/Components_Development__Series/001_walkthrough/ZKQuickNote
mask_component.swf
https://github.com/benbai123/ZK_Practice/blob/master/Components/demos/component_development_series/001_walkthrough/enhancedmask_component.swf
This comment has been removed by a blog administrator.
ReplyDeletedeleted since not meaningful for this article
Delete