users@javaserverfaces-spec-public.java.net

[jsr372-experts mirror] Fwd: [jsr372-experts] Re: Re: Handling focus after an Ajax update

From: Werner Punz <werner.punz_at_gmail.com>
Date: Thu, 16 Apr 2015 08:42:03 +0200

Hello everyone, here is the info as promised on how myfaces does it.

Following, first of all I have to apologize to all my users, I personally
think our focus code after
a second inspection is partially broken.

For simple input replaces we handle the focus handling automatically by
applying all attributes from the new element to the old one and erasing the
elements attributes which are not there anymore.
This code was donated by the icefaces guys and is always on per default
since it is uncritical.
The reason the focus stays is because the element never is fully replaced
just the attributes are.

Personally I think this code also is not entirely correct because it does
not erase any addEvent handlers some javascripts which might have been
added while a dom replacement always expected that those handlers are
erased.

We however have a more complex case in place also which you can turn on for
more complex components (aka components with embedded inputs) and this code
gets it 90% right:

a) it determines the active element and stores it in a local var. It also
stores the caret position.
b) It then does the html replacement
c) then it basically tries to find the replacement element in the dom and
tries to set to focus anew.
and tries to restore the caret position.

Now this code is not automatically turned on, and I now know why. (you
still can turn it on via a config param) The icefaces guys said this method
has sideeffects in some javascript code. And after a second inspection I
personally think neither the icefaces guys method nor my method is truly
the optimal implementation of the problem.

My way basically got it 90% right, but it needs to adapt to the onfocus
event if set, so following is needed.

a) store the element id of the activeElement and the caret position
b) do the html replacement
c) store any onfocus code which might be in the replacment, and erase it
c) focus the element
d) restore the caret position
e) readd the onfocus code

Any addEvent code is uncritical since the javascripts which are embedded
are not parsed at that stage and hence must be restored from the outside
where they were set at the first place.

I hope I have not overlooked something.

Btw. you can turn the more complicated case on, but be aware that the
onfocus for now.
use following code

window.myfaces = window.myfaces || {};
myfaces.config = myfaces.config || {};
myfaces.config.preserveFocus = true;

I will give my proposed method a proper testing in the upcoming days and if
it works out well, then I can drop the icefaces code and will turn my
method on.


Kind regards

Werner



On Mon, Apr 13, 2015 at 5:00 PM, Kito Mann <kito.mann_at_virtua.com> wrote:

> EB> What needs to change in the spec?
>
>
>> MM> Remembering the last active element would be a fine solution.
>
> MM> Or, we might introduce something like
>
> MM> <f:ajax execute="..." render="..." focus="elementId"/>
>
>
>> MM> elementId = someId|_at_this|_at_current
>
>
>> MM> The focus will be set only, and only if this optional attribute is
>
> MM> provided.
>
>
>> MM> Such an attribute might offer more flexibility than just the current
>
> MM> element.
>
>
>> I like the simplicity of this proposal but I think we need to specify a
>
> default behavior. How about we add to the spec that the ajax request
>
> should sample document.activeElement [1] before sending the request and
>
> set the focus to that element after doing the innerHTML replacement?
>
> For the attribute name, I prefer afterFocus. If the afterFocus
>
> attribute is set, the focus must be set to that element after the
>
> innerHTML replacement.
>
>
>> Ed
>
>
> The problem with solution is that the focus shouldn't move unless the user
> presses the TAB key. At the very least, that should be part of the spec.
> Otherwise if you the change event is fired without tab (such as with a
> SelectOneMenu or SelectManyCheckbox), the focus would jump that the next
> element unexpectedly. Also, one would need to specify previousFocus for
> shift-TAB.
>
> I would prefer, however, that the focus control is automatic, based on tab
> order. This can be done by retrieving all of the tabbable elements on the
> page and determining the one before or after the activeElement. The
> automatic focus feature could be turned off by default in web.xml. If we
> had this, I'm not sure the explicit functionality would sill be required.
>
>>
>> --
>> | edward.burns_at_oracle.com | office: +1 407 458 0017
>> | 1 days til CONFESS 2015
>>
>> [1] http://davidwalsh.name/focused-element
>>
>
>