-
FEATURED COMPONENTS
First time here? Check out the FAQ!
asked 2013-02-18 23:39:25 +0800
This post is a wiki. Anyone with karma >100 is welcome to improve it.
Hi,
I am building some kind of wizard based on a cardlayout. Each step of the wizard is displayed in a separate card. I have 5 cards with different components in them (textboxes, comboboxes, etc).
My idea was to let the user go through the wizard without having to use a mouse because it will be a pretty repetitive action.
Ideally, when the focus is set in the last field and the user presses the "Tab" key the card layout should slide,show the second card and put the focus in the first field. However, a bug is causing the card layout to only slide halfway through: I end up with half the card 1 on the left and half the card 2 on the right.
I ended up putting a "previous" and "next button" which works but throws a different problem: When the second card opens, I would like to set the focus in the first field of the card.
I have been listening to all kind of events but their doesn't seem to be an event fired once the card gets displayed.
So here is my question: Is there an event fired once the card gets displayed? If not, do you know of any fix to resolve that broken cardlayout sliding?
answered 2013-03-22 07:34:20 +0800
This post is a wiki. Anyone with karma >100 is welcome to improve it.
Regarding to change card by tab key, you can try override both client side and server side functions as needed, please refer to the sample below:
<zk>
<script><![CDATA[
zk.afterLoad("zul", function () {
var _wgt = {};
zk.override(zul.Widget.prototype, _wgt, {
/** override doFocus_ function
*/
doFocus_: function (evt) {
// do original function
_wgt.doFocus_.apply(this, arguments);
// apply to all widgets have class 'cardlayout-children'
if (jq(this.$n()).hasClass('cardlayout-children')) {
var cardlayout = this.parent,
idx = 0;
// find self index
for (var w = cardlayout.firstChild; w; w = w.nextSibling) {
if (w == this)
break;
idx++;
}
// fire event as needed
cardlayout.fire('onCustomSyncIndex', {focusedIndex: idx}, {toServer: true});
}
},
/** override doKeyDown_ function
*/
doKeyDown_: function (evt) {
// apply to all widgets have class 'cardlayout-children'
// if 'tab' clicked
if (jq(this.$n()).hasClass('cardlayout-children')
&& evt.keyCode == 9) {
var cardlayout = this.parent;
// prevent default action
evt.stop();
if (evt.shiftKey)
cardlayout.fire('onCustomGoPrevious', {}, {toServer: true});
else
cardlayout.fire('onCustomGoNext', {}, {toServer: true});
} else {
// call original function
_wgt.doKeyDown_.apply(this, arguments);
}
}
});
});
]]></script>
<zscript><![CDATA[
import org.zkoss.zk.au.AuRequest;
/** extends Cardlayout to process custom events
*/
public class CustomCardlayout extends Cardlayout {
public void service(AuRequest request, boolean everError) {
String cmd = request.getCommand();
if ("onCustomSyncIndex".equals(cmd)) {
int idx = Integer.parseInt(request.getData().get("focusedIndex").toString());
if (getSelectedIndex() != idx) {
setSelectedIndex(idx);
}
} else if ("onCustomGoNext".equals(cmd)) {
next();
getChildren().get(getSelectedIndex()).focus();
} else if ("onCustomGoPrevious".equals(cmd)) {
previous();
getChildren().get(getSelectedIndex()).focus();
} else {
super.service(request, everError);
}
}
}
]]></zscript>
<cardlayout use="CustomCardlayout" width="150px" height="200px">
<!-- specify sclass cardlayout-children to each child -->
<textbox width="150px" sclass="cardlayout-children" />
<button width="150px" label="test button" sclass="cardlayout-children" />
<datebox width="150px" sclass="cardlayout-children" />
</cardlayout>
</zk>
Thanks a lot, benbai! Your solution worked perfectly. The only tweaks I made was to eliminate the subclassed CustomCardlayout and change the javascript to fire events to the client side cardlayout widget. That way I can reuse the existing MVVM commands that I have for the buttons on my wizard:
zk.afterLoad("zul", function () {
var _wgt = {};
zk.override(zul.Widget.prototype, _wgt, {
/** override doKeyDown_ function
*/
doKeyDown_: function (evt) {
// apply to all widgets have class 'cardlayout-children'
// if 'tab' clicked
if (jq(this.$n()).hasClass('cardlayout-first')
&& evt.keyCode == 9
&& evt.shift) {
var cardlayout = zk.Widget.$('$card');
// prevent default action
evt.stop();
zAu.send(new zk.Event(cardlayout, 'onCustomGoPrevious', null), 10);
} else if (jq(this.$n()).hasClass('cardlayout-last')
&& evt.keyCode == 9
&& !evt.shift) {
var cardlayout = zk.Widget.$('$card');
// prevent default action
evt.stop();
zAu.send(new zk.Event(cardlayout, 'onCustomGoNext', null), 10);
} else {
// call original function
_wgt.doKeyDown_.apply(this, arguments);
}
}
});
});
<cardlayout id="card"
width="840px"
vflex="1"
selectedIndex="0"
onCustomGoNext="@command('nextCard')"
onCustomGoPrevious="@command('prevCard')">
Asked: 2013-02-18 23:39:25 +0800
Seen: 34 times
Last updated: May 15 '13