ZK - Open Source Ajax Java FrameworkZK - Open Source Ajax Java Framework

change focus to next component

sav
2 Apr 2009 08:57:40 GMT
2 Apr 2009 08:57:40 GMT

Hi,
I created an entry form using many components like textbox, listbox, etc.. I moved the focus from one entry field to the other field by pressing tab key on keyboard. How could I change that tab key function with another key (like enter or arrow key) ?
Many thanks..

--
sav

dennis
3 Apr 2009 02:08:47 GMT
3 Apr 2009 02:08:47 GMT

read the document about onOK and onCtrlKey
http://docs.zkoss.org/wiki/Component_Events#Keystroke_Events
listen onFocus to know who get the focus.
use focus() to change the focus

I am wondering a problem, how do you know which one should be the 'next' focus. you must have many control on it if you don't use default browser tab key.

sav
3 Apr 2009 07:43:43 GMT
3 Apr 2009 07:43:43 GMT

I will set the next focus to be the next sibling.
The problem is I want to make a generic function to detect the current focus and change to the next focus after I press enter key. But, I cannot get the current focus component, there is no such method like getFocus().
Or is there any alternative solution..

thanx,
--
sav

dennis
3 Apr 2009 10:54:18 GMT
3 Apr 2009 10:54:18 GMT

sorry, there is no generic getFocus method currently.
please post to feature request if there is not such one.

robertpic71Top Contributor
3 Apr 2009 11:54:54 GMT
3 Apr 2009 11:54:54 GMT

>> after I press enter key.
Why not process the enterkey?

<window id="root"  border="normal" 
            width="900px" height="90%" onOK="onEnter(event)">
	<grid>
            <rows>
               <row>
		LabelA
		<label id="labela" value="Value A" tooltip="help" />
		</row>
                <row>
                TextB
                <textbox id="textboxb" onBlur="onLeave(self)"/>
                </row>
                 <row>
                TextC
                <textbox id="textboxc" onBlur="onLeave(self)"/>
                  </row>
                  <row>
                TextD
                <textbox id="textboxd" onBlur="onLeave(self)"/>
                
                </row>
            </rows>
	</grid>
         <html id="helptext" content="test"/>
	<zscript>
                void onEnter(Event event) {
                      Component comp = event.getReference();
                      Component next = comp.getNextSibling(); 
                      helptext.content = "Enter for " + event.getReference().getId();
                      
                 } 
                 void onLeave(Component comp) {
                      helptext.content = "Leave field  " + comp.getId();
                 } 
        </zscript>
</window>

Check also the wiki entries:
How to Keep The Current Focused Component
Dynamic cursor/field-sensitiv help and tooltip

There is one drawback for all this resolutions: It is done serverside, and you need a server-roundtrip for a cursor-operation. However, no problem with a fast server and connection.

Find the next field could be a hard work. I.e. in this grid the getNextSibling() return null, you have to get the parent, nextSibling (=next Raw) and get the first Child which is an inputelement...

So maybe the better way is: to reuse the tabindex-defintion (scan the component tree) for the enter-key.

>> please post to feature request if there is not such one
getNextTab() (get next Component via taborder) or fire a tab-event could also be a resolution.

/Robert

sav
8 Apr 2009 08:38:02 GMT
8 Apr 2009 08:38:02 GMT

Many thanks.. ^:)^
So far, I tried ur solution to trap the enter key, and it works. Plus, to make it easily plugged into all my zuls, I created a component that add onOK event on the window and iteratively add onFocus to all components in the window on the fly. That way I could keep track on the focus element.
Yep, I wonder whether this way could decrease the performance..
And about tabindex, I couldn't find a way to make use of it, since I cannot find a method to fire tab key..

regards,
--
sav

mpg2005m
22 Oct 2009 09:39:18 GMT
22 Oct 2009 09:39:18 GMT

Hi, I had have the same problem and here post my solution, it works fine and you can change elements filter. This solution uses jquery but it very easy to implement, next I put the code, if anybody have or make a better solution, please send me :-))

First, I only use the onOK event in windows and with Clients.evalJavaScript make a call to the function with the event object uuid that makes de event.
After, I load jquery min and filter the components I want to tab into, find the position in that array and move to the next element, then put focus on it.
This works with ZK 3.0.6 I don't try this with early versions.

And that's all I hope it can help you.

<window id="frm" border="normal">
<attribute name="onOK">{
String cadena = "nextElement('" + event.reference.uuid + "')";
Clients.evalJavaScript(cadena);
}
</attribute>

<script src="./script/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
function nextElement(posActual){
var elements = jQuery('input:visible, textarea:visible, button:visible');
posActual = '#' + posActual;
var position = elements.index(jQuery(posActual));
elements.get(position+1).focus();
}
</script>
</window>

samchuang
22 Oct 2009 19:37:27 GMT
22 Oct 2009 19:37:27 GMT

Thanks ~

Use jquery and do it at client is a good idea ~~

mikehellsing
12 Mar 2010 20:56:12 GMT
12 Mar 2010 20:56:12 GMT

Hi, all..
I'm using Zk 5 CE, when i tried mpg2005m tips on my code to have a tab index when onOk function:

<attribute name="onOK">{
String cadena = "nextElement('" + event.reference.uuid + "')";
Clients.evalJavaScript(cadena);
}
</attribute>
<script src="/script/jquery-1.4.2.min.js"/>
<script type="javascript">
function nextElement(posActual){
var elements = jQuery('input:visible, textarea:visible, button:visible');
posActual = '#' + posActual;
var position = elements.index(jQuery(posActual));
elements.get(position+1).focus();
}
</script>

I got pop up window error :

Failed to process
script
nextElement is not defined

then I've tried & call an any very simple Javascript Function like:

function test() {
alert('testing success..');
}

And I got a same error, seem my page cannot call the Javascript function. Can anyone help me, or if there any solution for send key tab function with ENTER Key on Zk 5 CE. Thanks before.

Best Regards,

Maikel
(mike_hellsing@yahoo.com)

samchuang
14 Mar 2010 20:28:32 GMT
14 Mar 2010 20:28:32 GMT

Hi

if you have javascript error about function is not define, try to save the function in a .js file and load it by use

<?script type="text/javascript" src="/js/jquery-1.3.2.js"?>
<?script type="text/javascript" src="/js/your-function.js"?>

mikehellsing
17 Mar 2010 04:19:24 GMT
17 Mar 2010 04:19:24 GMT

Hi, thanks samchuang, i've tried your sugestion, but still can't call any javascript function with same error :(

mpg2005m
18 Mar 2010 14:03:39 GMT
18 Mar 2010 14:03:39 GMT

Hi, the example of my last post works quite fine until ZK 3.6.0 but sometimes the component we want to be focused isn't correct, so I have develop other choice using java, not jquery. Here we post the code, it works fine (I don't know even ZK 5), this is the problem: I need to go to next componet, but only if it's a InputElement or a Button, if you want to tab to other elements, only need that the element has the tabindex property set to a value (it`s index).

I hope you enjoy this, and if there are errors please post me or post the solution :-))

ZUL File:

<window id="frmExample" title="Example" border="normal" use="servlets.ExampleWindow" onOK="frmExample.nextElement(event.reference);">
... Put your components
</windows>

Java Class (package servlets)

public class ExampleWindow extends Window {
private ArrayList lstComponents;

public void onCreate(){
sortElements();
}

private void sortElements(){
lstComponents = new ArrayList();
for (Object element: this.getFellows()){
if (element instanceof InputElement)
lstComponents.add((InputElement) element);
else if (element instanceof Button)
lstComponents.add((Button) element);
}
Collections.sort(lstComponents, new Comparator<XulElement>(){

@Override
public int compare(XulElement o1, XulElement o2) {
int indexO1, indexO2;

indexO1 = getTabindex(o1);
indexO2 = getTabindex(o2);
if (indexO1 < indexO2)
return -1;
else if (indexO1 > indexO2)
return 1;
else
return 0;
}

private int getTabindex(XulElement object){
if (object instanceof InputElement)
return ((InputElement)object).getTabindex();
else if (object instanceof Button)
return ((Button)object).getTabindex();
else return 0;
}
});
}

public void nextElement(InputElement elem){
int index = 0;

for (Object element: lstComponents){
if (elem == element)
break;
index ++;
}
if (index+1 < lstComponents.size()){
if (lstComponents.get(index+1) instanceof InputElement)
((InputElement)lstComponents.get(index+1)).setFocus(true);
else
((Button)lstComponents.get(index+1)).setFocus(true);
}
}
}

samchuang
18 Mar 2010 21:13:36 GMT
18 Mar 2010 21:13:36 GMT

@mikehellsing

Hi, try to use firebug to check if the script file has loaded in the header, if not, maybe there are some typo.

by the way, do you need to import different jquery version? you could just use the ZK5 default jquery version