You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by ChambreNoire <aw...@tentelemed.com> on 2014/11/28 18:39:38 UTC

TextField cursor reset mid-editing

Hi,

I was wondering if there's a way around the following problem - at least a
slightly more elegant one than I came up with! 

When one adds an AjaxFormUpdatingBehavior("onkeyup") to a TextField, if
during the update the source TextField is added to the AjaxRequestTarget the
resulting behaviour is a TextField which periodically resets it's
cursor/caret position to zero (depending on the Behavior's throttle
settings). This is obviously problematic during typing.

In my particular case, the TextField in question is within a container
alongside the label, suffix and a bunch of status indicators (a super-field
of sorts). These all react to changes in the textfield content. When I'm
updating from outside it's not a problem but when the update comes from
within as a result of an onKeyUp update, I add the container to the
AjaxRequestTarget in order to get all the sub-components updated and thus
end up with the aforementioned cursor issue. 

I have worked around this by performing partial updates in this specific
case (all the siblings minus the offending textfield) and appending some
JQuery to the AjaxRequestTarget in order to update the container css class
but it's hardly ideal...

Any thoughts?

Thanks,

CN

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: FIXED: TextField cursor reset mid-editing

Posted by Martin Grigorov <mg...@apache.org>.
Thanks!

Martin Grigorov
Wicket Training and Consulting
https://twitter.com/mtgrigorov

On Thu, Dec 4, 2014 at 5:19 PM, ChambreNoire <aw...@tentelemed.com> wrote:

> OK so this is what I have. Disclaimer: I'm no javascript/jQuery expert so
> this is mostly cobbled together from things I have found online and tested
> in my particular situation. Any optimisations are more than welcome!
>
> So first the script
>
> (function($) {
>     $.fn.getCaretPosition = function() {
>         var input = this.get(0);
>         if (!input) return; // No (input) element found
>         if ('selectionStart' in input) {
>             // Standard-compliant browsers
>             return input.selectionStart;
>         } else if (document.selection) {
>             // IE
>             input.focus();
>             var sel = document.selection.createRange();
>             var selLen = document.selection.createRange().text.length;
>             sel.moveStart('character', -input.value.length);
>             return sel.text.length - selLen;
>         }
>     };
>     $.fn.setCaretPosition = function(position) {
>         var input = this.get(0);
>         if (!input) return false; // No (input) element found
>
>         input.value = input.value;
>         // ^ this is used to not only get "focus", but
>         // to make sure we don't have it everything -selected-
>         // (it causes an issue in chrome, and having it doesn't hurt any
> other browser)
>
>         if (input.createTextRange) {
>             var range = input.createTextRange();
>             range.move('character', position);
>             range.select();
>             return true;
>         } else {
>             // (input.selectionStart === 0 added for Firefox bug)
>             if (input.selectionStart || input.selectionStart === 0) {
>                 input.focus();
>                 input.setSelectionRange(position, position);
>                 return true;
>             } else  { // fail city, fortunately this never happens (as far
> as I've tested) :)
>                 input.focus();
>                 return false;
>             }
>         }
>     }
> })(jQuery);
>
> Then I add the following behavior to my TextField :
>
> add(new AjaxFormComponentUpdatingBehavior("onkeyup") {
>
>     @Override
>     protected void onUpdate(AjaxRequestTarget target) {
>
>         String id = getComponent().getMarkupId();
>
>         String caret = id + "_caretPosition";
>         String selector = "$('#" + id + "')";
>
>         target.prependJavaScript("var $s = " + selector +
> ";if($s[0]===document.activeElement){" +
>                 "jQuery.data(document,'" + caret + "'," + selector +
> ".getCaretPosition());}");
>
>         onFieldUpdate(getFormComponent(), target);
>
>         target.appendJavaScript("var $p = jQuery.data(document,'" + caret +
> "');" +
>                 "if($p!=undefined){" + selector + ".setCaretPosition($p);"
> +
>                 "jQuery.removeData(document,'" + caret + "');}");
>     }
>
>     @Override
>     protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
>         super.updateAjaxAttributes(attributes);
>
>         String id = getFormComponent().getMarkupId() + "_onkeyup";
>
>         attributes.setThrottlingSettings(new ThrottlingSettings(id,
> seconds(1), true));
>     }
> });
>
> So this gets round the 'zapping focus back to the original field after
> hitting tab' issue I experienced as the behavior will be called a bit after
> I hit tab due to the throttle settings but that won't affect whether the
> field is focused or not (it won't regain focus). So I can check this and
> bypass the whole thing if the field isn't focused simply by not storing the
> caret position and consequently not re-setting it.
>
> You'll notice I'm storing the caretPosition in 'document' using
> jQuery.data(). There's probably a more 'js/jquery best practices' way to do
> this. I should also be clearing the position once I set it (thinking out
> loud) so I'll add that above.
>
> CN
>
> --
> View this message in context:
> http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668635.html
> Sent from the Users forum mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

Re: FIXED: TextField cursor reset mid-editing

Posted by ChambreNoire <aw...@tentelemed.com>.
OK so this is what I have. Disclaimer: I'm no javascript/jQuery expert so
this is mostly cobbled together from things I have found online and tested
in my particular situation. Any optimisations are more than welcome!

So first the script

(function($) {
    $.fn.getCaretPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if ('selectionStart' in input) {
            // Standard-compliant browsers
            return input.selectionStart;
        } else if (document.selection) {
            // IE
            input.focus();
            var sel = document.selection.createRange();
            var selLen = document.selection.createRange().text.length;
            sel.moveStart('character', -input.value.length);
            return sel.text.length - selLen;
        }
    };
    $.fn.setCaretPosition = function(position) {
        var input = this.get(0);
        if (!input) return false; // No (input) element found

        input.value = input.value;
        // ^ this is used to not only get "focus", but
        // to make sure we don't have it everything -selected-
        // (it causes an issue in chrome, and having it doesn't hurt any
other browser)

        if (input.createTextRange) {
            var range = input.createTextRange();
            range.move('character', position);
            range.select();
            return true;
        } else {
            // (input.selectionStart === 0 added for Firefox bug)
            if (input.selectionStart || input.selectionStart === 0) {
                input.focus();
                input.setSelectionRange(position, position);
                return true;
            } else  { // fail city, fortunately this never happens (as far
as I've tested) :)
                input.focus();
                return false;
            }
        }
    }
})(jQuery);

Then I add the following behavior to my TextField :

add(new AjaxFormComponentUpdatingBehavior("onkeyup") {

    @Override
    protected void onUpdate(AjaxRequestTarget target) {

        String id = getComponent().getMarkupId();

        String caret = id + "_caretPosition";
        String selector = "$('#" + id + "')";

        target.prependJavaScript("var $s = " + selector +
";if($s[0]===document.activeElement){" +
                "jQuery.data(document,'" + caret + "'," + selector +
".getCaretPosition());}");

        onFieldUpdate(getFormComponent(), target);

        target.appendJavaScript("var $p = jQuery.data(document,'" + caret +
"');" +
                "if($p!=undefined){" + selector + ".setCaretPosition($p);" +
                "jQuery.removeData(document,'" + caret + "');}");
    }

    @Override
    protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
        super.updateAjaxAttributes(attributes);

        String id = getFormComponent().getMarkupId() + "_onkeyup";

        attributes.setThrottlingSettings(new ThrottlingSettings(id,
seconds(1), true));
    }
});

So this gets round the 'zapping focus back to the original field after
hitting tab' issue I experienced as the behavior will be called a bit after
I hit tab due to the throttle settings but that won't affect whether the
field is focused or not (it won't regain focus). So I can check this and
bypass the whole thing if the field isn't focused simply by not storing the
caret position and consequently not re-setting it.

You'll notice I'm storing the caretPosition in 'document' using
jQuery.data(). There's probably a more 'js/jquery best practices' way to do
this. I should also be clearing the position once I set it (thinking out
loud) so I'll add that above.

CN

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668635.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: FIXED: TextField cursor reset mid-editing

Posted by Martin Grigorov <mg...@apache.org>.
Also please share the working snippets of code.
Someone else may reuse it.

Martin Grigorov
Wicket Training and Consulting
https://twitter.com/mtgrigorov

On Wed, Dec 3, 2014 at 4:33 PM, Ernesto Reinaldo Barreiro <
reiern70@gmail.com> wrote:

> Please don't change subject: some e-mail client get lost and display it as
> a new thread.
>
> On Wed, Dec 3, 2014 at 3:20 PM, ChambreNoire <aw...@tentelemed.com> wrote:
>
> > Nevermind. I figured it out. I just needed to perform the check on the
> > prepend rather than the append.
> >
> > Thanks for the help!
> >
> > CN
> >
> > --
> > View this message in context:
> >
> http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668606.html
> > Sent from the Users forum mailing list archive at Nabble.com.
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
>
>
> --
> Regards - Ernesto Reinaldo Barreiro
>

Re: FIXED: TextField cursor reset mid-editing

Posted by Ernesto Reinaldo Barreiro <re...@gmail.com>.
Please don't change subject: some e-mail client get lost and display it as
a new thread.

On Wed, Dec 3, 2014 at 3:20 PM, ChambreNoire <aw...@tentelemed.com> wrote:

> Nevermind. I figured it out. I just needed to perform the check on the
> prepend rather than the append.
>
> Thanks for the help!
>
> CN
>
> --
> View this message in context:
> http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668606.html
> Sent from the Users forum mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>


-- 
Regards - Ernesto Reinaldo Barreiro

FIXED: TextField cursor reset mid-editing

Posted by ChambreNoire <aw...@tentelemed.com>.
Nevermind. I figured it out. I just needed to perform the check on the
prepend rather than the append.

Thanks for the help!

CN

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668606.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: TextField cursor reset mid-editing

Posted by ChambreNoire <aw...@tentelemed.com>.
I'm afraid that doesn't work . When the keyup behavior updates a field that
the user is editing, the refresh of its parent must cause the field to loose
focus and therefore the caret is never repositioned. Without the
'$('#id')[0] === document.activeElement' it works but, as previously
described, then tabbing between fields is a mess.

I dumped a boiled down quickstart illustrating this  here
<https://dl.dropboxusercontent.com/u/32242922/fields.zip>  .

The only way I see this working is by using some convoluted global variable
where the caret position is stored in a global variable, indexed against the
markupId and flushed by the onblur behavior to avoid repositioning. Seems
pretty crap...

CN

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668601.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: TextField cursor reset mid-editing

Posted by Martin Grigorov <mg...@apache.org>.
Hi,

You should bother to set the caret position only if the HTML for this
Component is the currently focused element.
You can check this with $('#id')[0] === document.activeElement

Martin Grigorov
Wicket Training and Consulting
https://twitter.com/mtgrigorov

On Tue, Dec 2, 2014 at 3:29 PM, ChambreNoire <aw...@tentelemed.com> wrote:

> Hi,
>
> I've got this working now but there's a catch:
>
> Given two textfields with both this enhanced onKeyup behavior and an onBlur
> behavior, if I quickly type something into the first field, press tab and
> start typing into the second field there is some strangeness with the field
> focusing.
>
> field1:onblur
> field1:onkeyup
> field2:onblur
> field2:onkeyup
> field1:onblur
>
> So on-screen this means that while I'm typing into the second field the
> focus is shifted back to the first and then to the second again. If I'm
> still typing when this happens, focus with go back to the first field after
> this. It's a mess.
>
> Can anyone think of a way around this? I tried making the onKeyUp
> setCaretPosition conditional upon field focus but this doesn't work as
> :focus returns false strangely...
>
> field.add(new AjaxFormComponentUpdatingBehavior("onkeyup") {
>
>     @Override
>     protected void onUpdate(AjaxRequestTarget target) {
>
>         String selector = "$('#" + getComponent().getMarkupId() + "').";
>
>         target.prependJavaScript(selector + "data.caretPosition = " +
> selector + "getCaretPosition();");
>
>         onFieldUpdate(getFormComponent(), target);
>
>         target.appendJavaScript(selector + "setCaretPosition(" + selector +
> "data.caretPosition);");
> }
>
> Many thanks,
>
> CN
>
> --
> View this message in context:
> http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668599.html
> Sent from the Users forum mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

Re: TextField cursor reset mid-editing

Posted by ChambreNoire <aw...@tentelemed.com>.
Hi, 

I've got this working now but there's a catch:

Given two textfields with both this enhanced onKeyup behavior and an onBlur
behavior, if I quickly type something into the first field, press tab and
start typing into the second field there is some strangeness with the field
focusing.

field1:onblur
field1:onkeyup
field2:onblur
field2:onkeyup
field1:onblur

So on-screen this means that while I'm typing into the second field the
focus is shifted back to the first and then to the second again. If I'm
still typing when this happens, focus with go back to the first field after
this. It's a mess.

Can anyone think of a way around this? I tried making the onKeyUp
setCaretPosition conditional upon field focus but this doesn't work as
:focus returns false strangely...

field.add(new AjaxFormComponentUpdatingBehavior("onkeyup") {

    @Override
    protected void onUpdate(AjaxRequestTarget target) {

        String selector = "$('#" + getComponent().getMarkupId() + "').";

        target.prependJavaScript(selector + "data.caretPosition = " +
selector + "getCaretPosition();");

        onFieldUpdate(getFormComponent(), target);

        target.appendJavaScript(selector + "setCaretPosition(" + selector +
"data.caretPosition);");
}

Many thanks,

CN

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668599.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: TextField cursor reset mid-editing

Posted by ChambreNoire <aw...@tentelemed.com>.
Many Thanks. 

That works fine as far as the cursor is concerned but it seems that on the
ajax call, if the textfield is smaller than the content it contains, the
content is scrolled back to the start (while the cursor stays where it
should be). I'm currently trawling the web for solutions to this.

CN

--
View this message in context: http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582p4668586.html
Sent from the Users forum mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: TextField cursor reset mid-editing

Posted by Martin Grigorov <mg...@apache.org>.
Hi,

Try to read the cursor position in #prependJavaScript(), store it
temporarily somewhere, and set the position again in #appendJavaScript().
See
http://stackoverflow.com/questions/2897155/get-cursor-position-in-characters-within-a-text-input-field
http://stackoverflow.com/questions/512528/set-cursor-position-in-html-textbox
and many more in the web.

Martin Grigorov
Wicket Training and Consulting
https://twitter.com/mtgrigorov

On Fri, Nov 28, 2014 at 6:39 PM, ChambreNoire <aw...@tentelemed.com> wrote:

> Hi,
>
> I was wondering if there's a way around the following problem - at least a
> slightly more elegant one than I came up with!
>
> When one adds an AjaxFormUpdatingBehavior("onkeyup") to a TextField, if
> during the update the source TextField is added to the AjaxRequestTarget
> the
> resulting behaviour is a TextField which periodically resets it's
> cursor/caret position to zero (depending on the Behavior's throttle
> settings). This is obviously problematic during typing.
>
> In my particular case, the TextField in question is within a container
> alongside the label, suffix and a bunch of status indicators (a super-field
> of sorts). These all react to changes in the textfield content. When I'm
> updating from outside it's not a problem but when the update comes from
> within as a result of an onKeyUp update, I add the container to the
> AjaxRequestTarget in order to get all the sub-components updated and thus
> end up with the aforementioned cursor issue.
>
> I have worked around this by performing partial updates in this specific
> case (all the siblings minus the offending textfield) and appending some
> JQuery to the AjaxRequestTarget in order to update the container css class
> but it's hardly ideal...
>
> Any thoughts?
>
> Thanks,
>
> CN
>
> --
> View this message in context:
> http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-tp4668582.html
> Sent from the Users forum mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>