Introduction
This article describe how to create a Yearbox/Monthbox based on Datebox with limited view.
The Program
datebox_with_limited_view.zul
<zk>
<!-- tested with ZK 6.0.2 -->
<script><![CDATA[
zk.afterLoad("zul.db", function () {
// Datebox Calendar Renderer
var _Cwgt = {};
zk.override(zul.db.CalendarPop.prototype, _Cwgt, {
// switch the view after redraw or open as needed
redraw: function (out) {
_Cwgt.redraw.apply(this, arguments); //call the original method
this._customChangeView ();
},
open: function (silent) {
_Cwgt.open.apply(this, arguments); //call the original method
this._customChangeView ();
},
_customChangeView: function () {
// cannot show month/day
if (jq(this.parent.$n()).hasClass('datebox-year-only')) {
var view = this._view;
// switch to year view as needed
if (view == 'month' || view == 'day')
this._setView("year");
} else if (jq(this.parent.$n()).hasClass('datebox-month-only')) {
// cannot show day view
// switch to month view as needed
if (this._view == 'day')
this._setView("month");
}
},
// customize the chooseDate function
_chooseDate: function (target, val) {
var view = this._view;
if (jq(this.parent.$n()).hasClass('datebox-month-only')
|| jq(this.parent.$n()).hasClass('datebox-year-only')) {
// do customize chooseDate if the parent (datebox)
// has specific class
var date = this.getTime(),
year = (view == 'decade' || view == 'year')? val : date.getFullYear(),
month = view == 'month'? val : 0,
date = 1;
// set date value
this._setTime(year, month, 1);
if (view == 'decade') {
// switch to year view if at decade view
this._setView("year");
} else if (jq(this.parent.$n()).hasClass('datebox-month-only')
&& view == 'year') {
// switch to month view if at year view and the month view is allowed
this._setView("month");
} else if (jq(this.parent.$n()).hasClass('datebox-month-only') && view == 'month'
|| jq(this.parent.$n()).hasClass('datebox-year-only') && view == 'year') {
// close calendar and update value if already at the smallest allowed view
this.close();
this.parent.updateChange_();
}
} else {
_Cwgt._chooseDate.apply(this, arguments); //call the original method
}
}
});
});
]]></script>
<vbox>
<label value="datebox that do not allow the month/day view" />
<datebox id="dbx" sclass="datebox-year-only"
format="yyyy">
<attribute name="onChange"><![CDATA[
Date date = self.getValue();
alert("Year: " + (date.getYear()+1900));
]]></attribute>
</datebox>
<label value="datebox that do not allow the day view" />
<datebox id="dbx2" sclass="datebox-month-only"
format="yyyy-MM">
<attribute name="onChange"><![CDATA[
Date date = self.getValue();
alert("Year: " + (date.getYear()+1900) + "\n"
+ "Month: " + (date.getMonth()+1));
]]></attribute>
</datebox>
<label value="a normal datebox" />
<datebox id="dbx3">
<attribute name="onChange"><![CDATA[
Date date = self.getValue();
alert("Year: " + (date.getYear()+1900) + "\n"
+ "Month: " + (date.getMonth()+1) + "\n"
+ "Day: " + date.getDate());
]]></attribute>
</datebox>
</vbox>
</zk>
The Result
View demo online
http://screencast.com/t/EejPLWg1iLyx
Reference
Datebox.js
https://github.com/zkoss/zk/blob/6.0-Stable/zul/src/archive/web/js/zul/db/Datebox.js
Calendar.js
https://github.com/zkoss/zk/blob/6.0-Stable/zul/src/archive/web/js/zul/db/Calendar.js
ZK Client Side Programming
http://books.zkoss.org/wiki/Small_Talks/2010/April/Client_Side_Programming
Download
Files at github:
datebox_with_limited_view.zul
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/WebContent/datebox_with_limited_view.zul
datebox_with_limited_view.swf
https://github.com/benbai123/ZK_Practice/blob/master/Components/demos/datebox_with_limited_view.swf
Hi
ReplyDeleteHow we can create that as separate ZK Component, so that if i want to use this in multiple zul pages, then i do not want copy and paste the code in every zul file.
You can define a component extends datebox then do customization, I'll describe it in another article this weekend.
DeleteHi
ReplyDeleteI tried myself. Here is the link.
http://emrpms.blogspot.in/2013/01/zk-datebox-customize-datebox-as.html
But still my objective is not solved. You can see my objective at the bottom of the post.
Can you please help me ?
ReplyDeleteSure, I'll do it these two days.
DeleteDone, http://ben-bai.blogspot.tw/2013/01/extending-and-customizing-zk-component.html
DeleteHi,
ReplyDeleteIs this working on zk 5? Cause i tried this on zk 5 and still no luck. Please help,,
Probably the js api is changed, I'll check this.
Deletejust remove the redraw function then it should work
Deletethe redraw function:
// switch the view after redraw or open as needed
redraw: function (out) {
_Cwgt.redraw.apply(this, arguments); //call the original method
this._customChangeView ();
},
It works,,
Deletethanks
No problem, I'm happy to be helpful :)
DeleteThis great solution seems not work at the latest ZK7,
ReplyDeleteAfter selecting month,then the box is still empty!
Yes, dom structure changed in ZK7, almost need to redo all customization for ZK7.
DeleteIs there a solution for ZK7?
DeleteYes, please refer to
Deletehttp://zkfiddle.org/sample/ld4v50/1-ZK7-Monthbox-Yearbox
pastebin backup
Deletehttp://pastebin.com/zmhexXZ2
Perfect! Thanks for this post.
ReplyDeleteIs it possible to take the constraint into account to forbidden the user to click on a wrong year/month ?
For example, if I put the constraint "after 20130101" on the "yearbox", I can click on 2012 and the error message is displayed.
You can store a valid date and reset the value of datebox when error occured, please refer to https://gist.github.com/benbai123/8277053
DeleteI want to add a custom clear button with datebox to clear the value of datebox when datebox readonly attribute is set to true.
ReplyDeleteprobably you can use custom datebox and override setReadable method as below:
Deletepublic void setReadbale (boolean readable) {
if (readable) setValue("");
super.setReadable();
}
why an extra button is needed? For some specific flow or purpose?
In my application lots of dateboxes are there.I restrict the user only to select the date not to enter. But in some cases I need to clear the date. Because of read only I am not able to clear it manually. I need to customize the datebox in a single place which will reflect other places.Thats y I want clear cutomized datebox
DeleteThis comment has been removed by the author.
DeleteYou can either clear it with a button click or key event, please refer to https://gist.github.com/benbai123/8616110
DeleteHi ben,
ReplyDeleteif I am doing this method in my custom Datebox extended datebox class
public void setReadonly(boolean readable) {
if (readable)
setValue(null);
super.isReadonly();
}
It allows the user to enter the values which I donot want.
my fault, it should be super.setReadonly(readable);
DeleteHi ben,
ReplyDeletePlease look at this question
http://stackoverflow.com/questions/21274789/zk-customize-calender-popup
just replied
DeleteHello Ben, while the post is a little old, I would like to ask you how can I create a datebox displaying (and limiting selection) to year ONLY.
ReplyDeletePlease refer to this one for ZK7
Deletehttp://zkfiddle.org/sample/ld4v50/1-ZK7-Monthbox-Yearbox
It works well with ZK 8.0.3