8 Replies Latest reply on Feb 10, 2012 5:24 AM by Nicholas Oxhøj

    s:defaultAction blocks newlines in textarea

    Nicholas Oxhøj Newbie

      Hi


      I discovered that there seems to be a problem with using <s:defaultAction> in forms with textareas. The problem is that <s:defaultAction> captures ALL keypresses on Enter and submits the form - even when the cursor is in a textarea, .


      I don't think there is currently any workaround for using <s:defaultAaction> on forms with textareas, so I can't understand, that this issue seems to go unnoticed - and why more people apparently don't have a problem with this: Googling for s:defaultaction and textarea, basically have this issue report as it's only hit: JBSEAM-4648


      Does anybody have any good solutions/workarounds for using <s:defaultAaction> on forms with textareas? Or how do you handle this use case?

        • 1. Re: s:defaultAction blocks newlines in textarea
          Nikolay Elenkov Master

          Override the form's onkeypress event handler to handle newlines differently for text area tags (insert new line) and everything else (execute default action).

          • 2. Re: s:defaultAction blocks newlines in textarea
            Nicholas Oxhøj Newbie
            Seems like it would make sense for the Seam developers to implement this small fix for <s:defaultaction>.

            But until that might happen some day, you are saying to simply not use <s:defaultAction> on forms with text areas and instead implement the <s:defaultAction> functionality yourself on those forms (handling text areas more sensibly)?

            I was also thinking of implementing a new renderer for <s:defaultaction>, extending org.jboss.seam.ui.renderkit.DefaultActionRendererBase and simply override doEncodeEnd(), copying the code from DefaultActionRendererBase.doEncodeEnd(), just adding a special case for text areas. Especially, since I use the same set of buttons (where one of them has <s:defaultAction>) on many pages, and only a couple of these actually have text areas.

            • 3. Re: s:defaultAction blocks newlines in textarea
              Nikolay Elenkov Master

              Nicholas Oxhøj wrote on Mar 07, 2011 02:47:


              Seems like it would make sense for the Seam developers to implement this small fix for <s:defaultaction>.


              File a JIRA, you might get lucky: )



              But until that might happen some day, you are saying to simply not use <s:defaultAction> on forms with text areas and instead implement the <s:defaultAction> functionality yourself on those forms (handling text areas more sensibly)?


              You can still use <s:defaultAction> to mark the default button, but basically, yes.



              I was also thinking of implementing a new renderer for <s:defaultaction>, extending org.jboss.seam.ui.renderkit.DefaultActionRendererBase and simply override doEncodeEnd(), copying the code from DefaultActionRendererBase.doEncodeEnd(), just adding a special case for text areas. Especially, since I use the same set of buttons (where one of them has <s:defaultAction>) on many pages, and only a couple of these actually have text areas.


              That's doable too, but a PITA with JSF. Just adding your monkey patched JS handlers to the relevant pages is easier (that's what we did).

              • 4. Re: s:defaultAction blocks newlines in textarea
                Nicholas Oxhøj Newbie

                Nikolay Elenkov wrote on Mar 07, 2011 03:13:


                File a JIRA, you might get lucky: )



                You mean besides JBSEAM-4648? That one seems to describe the problem pretty well, don't you think?



                Nikolay Elenkov wrote on Mar 07, 2011 03:13:


                You can still use <s:defaultAction> to mark the default button, but basically, yes.



                If you continue to use <s:defaultAction>, how will you prevent the keypresshandler, that it installs on the form, from submitting the form?

                Having your own keypresshandler on the textarea, which prevents the event from bubbling up?
                Something like:


                <rich:jQuery selector="#textareaid" query="keypress(function(e){if (e.which == 13) e.stopPropagation()})"/>


                Or did you have something simpler in mind?

                • 5. Re: s:defaultAction blocks newlines in textarea
                  Nikolay Elenkov Master

                  Nicholas Oxhøj wrote on Mar 10, 2011 06:31:



                  Nikolay Elenkov wrote on Mar 07, 2011 03:13:


                  File a JIRA, you might get lucky: )



                  You mean besides JBSEAM-4648? That one seems to describe the problem pretty well, don't you think?


                  Sorry, I didn't read it the previous time. Should be sufficient.




                  Nikolay Elenkov wrote on Mar 07, 2011 03:13:


                  You can still use <s:defaultAction> to mark the default button, but basically, yes.



                  If you continue to use <s:defaultAction>, how will you prevent the keypresshandler, that it installs on the form, from submitting the form?

                  Having your own keypresshandler on the textarea, which prevents the event from bubbling up?
                  Something like:

                  <rich:jQuery selector="#textareaid" query="keypress(function(e){if (e.which == 13) e.stopPropagation()})"/>

                  Or did you have something simpler in mind?


                  We did it in straight JavaScript, but yes, pretty much the same thing. Check the even code, and if it is something other than 13, call click() on the defaultAction form, otherwise just insert a newline.


                  As to why it isn't fixed, Seam 2 was pretty much left out to dry at some point, so I guess people just gave up on it (including me). It has been getting some patch releases lately, and there is even talk about Seam 2.3. I guess some people who bought EAP complained loud enough for RedHat to care.




                  • 6. Re: s:defaultAction blocks newlines in textarea
                    Nicholas Oxhøj Newbie

                    Actually the problem with <s:defaultAction/> is even worse, as the keypress handler also intercepts Enter on other buttons and links inside the form, thus activating the default action, even when focus is on another button (e.g. a reset or cancel button).


                    I ended up creating my own defaultAction tag, which basically generates the same javascript as <s:defaultAction/>, but only intercepts Enter in INPUTs of type text, password, radio & checkbox:


                    document.forms['formid'].onkeypress = function(e) {
                        var keycode;
                        if (!e)
                            var e = window.event;
                        if (e.keyCode)
                            keycode = e.keyCode;
                        else if (e.which)
                            keycode = e.which;
                        if (keycode == 13) {
                            var target;
                            if (e.target)
                                target = e.target;
                            else if (e.srcElement)
                                target = e.srcElement;
                            if (target.tagName == 'INPUT' && (target.type == 'text' || target.type == 'password' || target.type == 'radio' || target.type == 'checkbox')) {
                                document.getElementById('actionComponentId').click();
                                return false;
                            }
                        }
                        return true;
                    };




                    I seriously think that this is what users of <s:defaultAction/> would expect...

                    • 7. Re: s:defaultAction blocks newlines in textarea
                      Lucas Lins Newbie

                      I did almost the same thing as you.


                      I extend the class DefaultActionRendererBase, then overwrite the method doEncodeEnd changing the string functionBody to the following content:



                      String functionBody = "{var keycode;"
                                            + "if (window.event) keycode = window.event.keyCode;"
                                            + "else if (event) keycode = event.which;"
                                            + "else return true;" 
                                            + "if (keycode == 13){"
                                            + "               var target;"
                                            + "               if (event.target) target = event.target;"
                                            + "               else if (event.srcElement) target = event.srcElement;"
                                            + "               if(target.tagName != 'TEXTAREA') {" 
                                            + "                       document.getElementById('" + actionComponentId  + "').click();" 
                                            + "                       return false; " 
                                            + "               }else return true;"
                                            + "}else return true; }";
                      



                      Finally, I set the new renderer in faces-config:



                      <renderer>
                         <component-family>org.jboss.seam.ui.DefaultAction</component-family>
                         <renderer-type>org.jboss.seam.ui.DefaultActionRenderer</renderer-type>
                         <renderer-class>com.miranteinfo.seam.jsf.renderer.defaultaction.DefaultActionRenderer</renderer-class>
                      </renderer>
                      



                      By doing this, I can use the defaultAction tag normally.

                      • 8. Re: s:defaultAction blocks newlines in textarea
                        Nicholas Oxhøj Newbie

                        Hmm, I just found a problem with the proposed solutions (including my own).

                         

                        The problem is that we want the user to actually be able to press "Enter" to create a new line in a textarea. But to implement keyboard navigation in custom components, at least OpenFaces often place the focus in a "hidden" (not using "display:none" or "visibility:hidden", but just placed outside the visible window) textarea to listen to keyboard events. And, as you probably guessed by now, the defaultAction does not work if the focus is currently placed in e.g. an OpenFaces DataTable or an OpenFaces TreeTable

                         

                        Unfortunately I currently don't have any good suggestions on how to work around this issue. I am not very keen on starting to check for e.g. OpenFaces specific classes (like "o_hiddenFocus") in the code for defaultAction...