0

Intercepting tab selection [closed]

asked 2011-12-09 11:46:10 +0800

avidD gravatar image avidD
166 2

Hello colleagues,
I have the following problem:
I have various tabs for different groups of properties of resources that can be edited in forms on these tabs. Some of the tabs require unsaved changes to be applied or discarded before switching to certain other tabs. To implement this, I assigned the tabs to groups. Whenever the tab group changes, I open a dialog and ask the user to apply, discard, or cancel. Everything works fine now except that the tab is switched independently of my dialog.
So what I need to do is somehow intercept the the select-event sent to the tab(box) so that selectTabDirectly(...) is not called on the tab box if the user cancels switching of the tab. Does anyone know how to achieve that?

Thanks beforehand,
David

delete flag offensive retag edit

The question has been closed for the following reason "too localized" by sjoshi
close date 2013-02-08 07:22:37

15 Replies

Sort by ยป oldest newest

answered 2011-12-09 14:36:42 +0800

gganassin gravatar image gganassin flag of Luxembourg
540 6
http://www.hybris.com/

updated 2011-12-09 14:39:16 +0800

I had the same thing to implement and that's what i did:

1 - made my own implementation of org.zkoss.zk.ui.util.EventInterceptor interface... let's call this TabboxEventInterceptor
2 - registered the interceptor in the desktop with Executions.getCurrent().getDesktop().addListener(new TabboxEventInterceptor())

Then you are able to intercept all the events you need before or after they are processed or event posted: if you want to stop the event because there are pending chances... you can just return null as event instrade of returning the original one and that's it!

link publish delete flag offensive edit

answered 2011-12-12 09:52:07 +0800

avidD gravatar image avidD
166 2

First of all, thanks for the prompt advice. However, it doesn't seem to work. The tab switches before the interceptor is called. Here is my interceptor:

private class TabSelectEventInterceptor implements EventInterceptor {
    @Override
    public Event beforeSendEvent(Event event) {
      LOG.info("beforeSendEvent");
      return event;
    }
    @Override
    public Event beforePostEvent(Event event) {
      LOG.info("beforePostEvent");
      if ( event instanceof SelectEvent && 
           event.getTarget() instanceof Tab && 
           event.getTarget().getId().equals("mNodes")) {
        return null;        
      }
      return event;
    }
    @Override
    public Event beforeProcessEvent(Event event) {
      LOG.info("beforeProcessEvent");
      return event;
    }
    @Override
    public void afterProcessEvent(Event event) {
      LOG.info("afterProcessEvent");
    }
  }

Apparently, the tab is switched already on the client side before / in parallel to sending the request to the server. Event if I put a breakpoint int DHtmlUpdateServlet.service(req, res), the tab switches before anything else happens. Probably, I need to override the javascript?

Cheers,
David

link publish delete flag offensive edit

answered 2011-12-13 08:02:08 +0800

gganassin gravatar image gganassin flag of Luxembourg
540 6
http://www.hybris.com/

Hi David,

i said that i had to do the same thing but that i've checked... it's not true: my concern was about closable tabs and pending changes: in that case Tabbox & EventInterceptor are working fine.

In case of selection instead i confirm your problem: it seems that even returning a null event... the selection of tab is processed absolutelly BEFORE the interceptor is triggered.

	@Override
	public Event beforePostEvent(Event event) {
		if (event instanceof SelectEvent && event.getTarget() instanceof Tab) {
			Tab t = (Tab) event.getTarget();
			Tabbox tb = (Tabbox) t.getParent().getParent();
			System.out.println(tb.getSelectedIndex());
			return null;
		}
		return event;
	}

In fact when beforePostEvent is called.... the selected index of the Tabbox is changed already. Meh!

link publish delete flag offensive edit

answered 2011-12-13 09:16:34 +0800

avidD gravatar image avidD
166 2

Hi gganassin,
you don't happen to have an idea how I can intercept the javascript?

Cheers,
David

link publish delete flag offensive edit

answered 2011-12-13 10:53:15 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi David,

It can be done by override doClick_ method of tab,
please refer to the sample below.

ZKFiddle-Link

index.zul
<zk>
<script type="text/javascript"><![CDATA[
zk.afterLoad("zul.tab", function () {
var originClick = zul.tab.Tab.prototype.doClick_;
var originUnbind = zul.tab.Tab.prototype.unbind_;
zul.tab.Tab.prototype.doClick_ = function (evt) {
if (this._preventSelect) {
evt.stop();
return;
}
originClick.apply(this, arguments);
}
zul.tab.Tab.prototype.unbind_ = function () {
this._preventSelect = null;
originUnbind(this, arguments);
}
});
]]></script>
<tabbox id="tabbox" width="400px">
<tabs id="tabs">
<tab id="tabOne" label="tabOne" closable="true" />
<tab id="tabTwo" label="tabTwo" closable="true" />
</tabs>
<tabpanels id="tabpanels">
<tabpanel id="panelOne">
panel one
</tabpanel>
<tabpanel id="panelTwo">
panel two
</tabpanel>
</tabpanels>
</tabbox>
<checkbox label="prevent select tab1">
<attribute name="onCheck">
if (self.checked)
Clients.evalJavaScript("zk.Widget.$(jq('$tabOne')[0])._preventSelect = true");
else
Clients.evalJavaScript("zk.Widget.$(jq('$tabOne')[0])._preventSelect = null");
</attribute>
</checkbox>
<checkbox label="prevent select tab2">
<attribute name="onCheck">
if (self.checked)
Clients.evalJavaScript("zk.Widget.$(jq('$tabTwo')[0])._preventSelect = true");
else
Clients.evalJavaScript("zk.Widget.$(jq('$tabTwo')[0])._preventSelect = null");
</attribute>
</checkbox>
</zk>

Regards,
ben

link publish delete flag offensive edit

answered 2011-12-14 01:55:25 +0800

jimmyshiau gravatar image jimmyshiau
4921 5
http://www.zkoss.org/ ZK Team

Hi All,

I have done it in a different way. For your reference:


TestComposer.java
package j23b6j9g$v2;

import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.ForwardEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Tab;

public class TestComposer extends GenericForwardComposer {

public void onSwitchTab(ForwardEvent event) throws InterruptedException {
final Tab tab = (Tab) event.getOrigin().getTarget();
Messagebox.show("Are you sure to leave?", "Exit",
Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION,
new EventListener() {

public void onEvent(Event event) throws Exception {
String evtName = event.getName();

if (Messagebox.ON_OK.equals(evtName)) {
tab.setSelected(true);
} else if (Messagebox.ON_CANCEL.equals(evtName)) {
//do nothing
}

}
});

}
}


index.zul
<zk xmlns:w="client">
<script type="text/javascript"><![CDATA[
function switchTab(notify, init){
if (this.desktop && !init && notify)
zAu.send(new zk.Event(this, 'onSwitchTab'));
else
this.$_sel(notify, init); //call the original method
}
]]></script>
<window apply="j23b6j9g$v2.TestComposer">
<tabbox width="300px">
<tabs>
<tab label="tab 1" w:_sel="switchTab" forward="onSwitchTab=onSwitchTab"/>
<tab label="tab 2" w:_sel="switchTab" forward="onSwitchTab=onSwitchTab"/>
</tabs>
<tabpanels>
<tabpanel>
<window title="win1" border="normal"></window>
</tabpanel>
<tabpanel>
<window title="win2" border="normal"></window>
</tabpanel>
</tabpanels>
</tabbox>
</window>
</zk>

link publish delete flag offensive edit

answered 2011-12-14 15:25:06 +0800

gganassin gravatar image gganassin flag of Luxembourg
540 6
http://www.hybris.com/

Whoa!
That's usable! thanks Jimmy!

link publish delete flag offensive edit

answered 2011-12-15 16:30:57 +0800

avidD gravatar image avidD
166 2

Hello Jimmy,
this solution looks great. However, I still got problems. I get this exception:

15.12.2011 17:27:28 org.zkoss.zk.ui.impl.UiEngineImpl handleError:1353
FATAL: >>org.zkoss.zk.ui.UiException: Only one child is allowed: <West gBHQo1#mWest>
>>	at org.zkoss.zul.LayoutRegion.beforeChildAdded(LayoutRegion.java:343)
>>	at org.zkoss.zk.ui.AbstractComponent.insertBefore(AbstractComponent.java:1129)
>>	at org.zkoss.zk.ui.impl.AbstractUiFactory.newComponent(AbstractUiFactory.java:96)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:808)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:777)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:686)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:748)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:708)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:650)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.createComponents(UiEngineImpl.java:1026)
>>	at org.zkoss.zk.ui.impl.AbstractExecution.createComponents0(AbstractExecution.java:253)
>>	at org.zkoss.zk.ui.impl.AbstractExecution.createComponents(AbstractExecution.java:245)
>>	at org.zkoss.zk.ui.Executions.createComponents(Executions.java:179)
>>	at com.tailor.gui.LayerComposer.doAfterCompose(LayerComposer.java:87)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.doAfterCompose(UiEngineImpl.java:523)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:831)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:777)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:686)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:748)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:708)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:650)
>>	at org.zkoss.zk.ui.impl.UiEngineImpl.createComponents(UiEngineImpl.java:1026)
>>	at org.zkoss.zk.ui.impl.AbstractExecution.createComponents0(AbstractExecution.java:253)
>>	at org.zkoss.zk.ui.impl.AbstractExecution.createComponents(AbstractExecution.java:245)
>>	at org.zkoss.zk.ui.Executions.createComponents(Executions.java:179)
>>	at com.tailor.gui.CenterStage.putOnDesktop(CenterStage.java:139)
>>	at com.tailor.gui.explorers.ExplorerUtils.createLayers(ExplorerUtils.java:127)
>>	at com.tailor.gui.listener.SwitchExplorerListener.onEvent(SwitchExplorerListener.java:90)
>>	at com.tailor.gui.listener.SwitchExplorerListener.onEvent(SwitchExplorerListener.java:1)
>>	at org.zkoss.zk.ui.AbstractComponent.onEvent(AbstractComponent.java:2706)
>>	at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:2675)
>>	at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:143)
>>	at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.process0(EventProcessingThreadImpl.java:534)
>>	at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.run(EventProcessingThreadImpl.java:461)

15.12.2011 17:27:29 org.zkoss.zk.ui.impl.DesktopImpl service:715
FATAL: [Desktop z_uws:/index.zul] client error: Failed to process 
setAttr
Cannot read property 'style' of undefined (TypeError)

What am I doing wrong?

Thanks beforehand,
David

link publish delete flag offensive edit

answered 2011-12-15 16:54:53 +0800

Matze2 gravatar image Matze2
773 7

Looks like you have more than one child in the "west" region of your borderlayout.

link publish delete flag offensive edit

answered 2011-12-15 17:23:03 +0800

twiegand gravatar image twiegand
1807 3

To illustrate Matze2's point:

FAIL

<borderlayout>
	<west>
		<label value="XXXXXX"/>
		<textbox />
	</west>
</borderlayout>

Good

<borderlayout>
	<west>
		<div>
			<label value="XXXXXX"/>
			<textbox />
		</div>
	</west>
</borderlayout>

Just wrap your code in the west section with a <div> so it only "sees" one child.

Hope that helps.

Todd

link publish delete flag offensive edit

Question tools

Follow

RSS

Stats

Asked: 2011-12-09 11:46:10 +0800

Seen: 747 times

Last updated: Jan 21 '13

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More