Google Chrome Mobile (Nexus 7) | Form submission not working
Asked Answered
C

1

11

I have an issue with logging into my website that appears to manifest in the mobile chrome browser (but works for the web-kit browser provided in some phones). I'm working trying to get into a "developer mode" on a tablet but I'm hoping someone else has run into this issue and can point me in the right direction while I figure out how to actually debug this.

Its a JSF2 Application (Primefaces over Bootstrap2.2) as the UI.

My form looks like this (second set of 'onblur' calls are intentional to see if that helped it--which it did not):

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:composite="http://java.sun.com/jsf/composite" 
>
    <composite:interface>
        <composite:attribute name="user" />
        <composite:attribute name="pass" />
        <composite:attribute name="error" />
        <composite:attribute name="loggedIn" />
        <composite:attribute 
            name="loginAction" 
            method-signature="void actionListener(javax.faces.event.ActionEvent)"
        />
        <composite:attribute 
            name="logoutAction" 
            method-signature="void actionListener(javax.faces.event.ActionEvent)"
        />
    </composite:interface>

    <composite:implementation>
        <script type="text/javascript">
        function copyValue(sourceId, targetId){
            var source = '#{cc.attrs.id}:' + sourceId;
            var target = '#{cc.attrs.id}:' + targetId;

            var sourceEl = document.getElementById(source);
            var targetEl = document.getElementById(target); 

            targetEl.value = sourceEl.value; 
        };
        </script>
        <h:form class="navbar-form pull-right" id="login" prependId="false" rendered="#{not cc.attrs.error and !cc.attrs.loggedIn}">
            <h:panelGroup rendered="#{!cc.attrs.loggedIn}" layout="span">
                <h:inputHidden value="#{cc.attrs.user}" id="userText"/>
                <h:inputHidden value="#{cc.attrs.pass}" id="passValue"/>

                <input 
                    class="span2" 
                    type="text" 
                    placeholder="Username" 
                    id="#{cc.attrs.id}:userText_a"
                >
                </input>
                <input 
                    class="span2" 
                    type="password" 
                    placeholder="Password"
                    id="#{cc.attrs.id}:passValue_a"
                >
                </input>

                <h:commandButton 
                    class="btn" 
                    value="Sign in"
                    onclick="copyValue('userText_a', 'userText'); copyValue('passValue_a', 'passValue');"
                    actionListener="#{cc.attrs.loginAction}"
                />
                <!-- onblur="copyValue('userText_a', 'userText'); copyValue('passValue_a', passValue);" -->
            </h:panelGroup>
        </h:form>

        <h:form class="navbar-form pull-right" id="login_error" prependId="false" rendered="#{cc.attrs.error and !cc.attrs.loggedIn}">
            <h:panelGroup rendered="#{!cc.attrs.loggedIn}" layout="span" styleClass="control-group error" style="display:inline-block;">
                <h:inputHidden value="#{cc.attrs.user}" id="userText_e"/>
                <h:inputHidden value="#{cc.attrs.pass}" id="passValue_e"/>

                <input 
                    class="span2" 
                    type="text" 
                    placeholder="Username" 
                    id="#{cc.attrs.id}:userText_b"
                    onblur="document.getElementById('#{cc.attrs.id}:userText_e').value = this.value;"
                >
                </input>
                <input 
                    class="span2" 
                    type="password" 
                    placeholder="Password"
                    id="#{cc.attrs.id}:passValue_b"
                    onblur="document.getElementById('#{cc.attrs.id}:passValue_e').value = this.value;"
                >
                </input>

                <h:commandButton 
                    class="btn" 
                    value="Sign in"
                    actionListener="#{cc.attrs.loginAction}"
                    onclick="copyValue('userText_b', 'userText_e'); copyValue('passValue_b', 'passValue_e');"
                />
                <br />
                <span style="color:orange;">Login failed: Invalid username or password</span>               
            </h:panelGroup>
        </h:form>

        <h:form class="navbar-form pull-right" rendered="#{cc.attrs.loggedIn}"> 
            <h:panelGroup class="span2" style="display: inline-block;">
                <h:commandLink 
                    value="#{cc.attrs.user} | Sign Out" 
                    class="btn btn-primary"
                    actionListener="#{cc.attrs.logoutAction}"
                />
            </h:panelGroup>
        </h:form>
    </composite:implementation>
</html>

To be clear, I can log in on the desktop using Chrome/IE8+/Firefox/Opera and mobile I only have the issue with Chrome (I have not tried an iOS browser yet). The password submission isn't copied to the values of the hidden input prior to the post.

This might not be the best design and I'm open to suggestion. Dragging in the <h:inputText /> components complicates the styling as I'm already replying heavily on Primefaces/Bootstrap and screws up the layout hence this "work-around".

Cherimoya answered 19/11, 2012 at 21:20 Comment(3)
can you confirm it's the mobile chrome browser and the default android browser (common misconception - the default browser isn't Chrome)?Turgeon
Oh it is definitely Chrome, the default browser (SlimBean's browser) works fine.Cherimoya
I should note, I SlimBean is running on a phone, not the Nexus 7 and Chrome fails on the the SlimBean device as well. The default browser works on this device, Chrome doesn't.Cherimoya
D
1

instead of

            <input 
                class="span2" 
                type="text" 
                placeholder="Username" 
                id="#{cc.attrs.id}:userText_b"
                onblur="document.getElementById('#{cc.attrs.id}:userText_e').value = this.value;"
            >
            </input>
            <input 
                class="span2" 
                type="password" 
                placeholder="Password"
                id="#{cc.attrs.id}:passValue_b"
                onblur="document.getElementById('#{cc.attrs.id}:passValue_e').value = this.value;"
            >
            </input>

            <h:commandButton 
                class="btn" 
                value="Sign in"
                actionListener="#{cc.attrs.loginAction}"
                onclick="copyValue('userText_b', 'userText_e'); copyValue('passValue_b', 'passValue_e');"
            />

try not setting an onblur property in the username and the password input, because the onBlur property may get tricky in mobile phones.

Instead, try doing everything inside the onClick event. i would do everything inside one function:

            <h:commandButton 
                class="btn" 
                value="Sign in"
                actionListener="#{cc.attrs.loginAction}"
                onclick="submitForm()"
            />

and inside the function:

function submitForm()
{
    var objUserText_e = document.getElementById('#{cc.attrs.id}:userText_e');
    var objUserText_b = document.getElementById('#{cc.attrs.id}:userText_b');

    var passValue_e = document.getElementById('#{cc.attrs.id}:userText_e');
    var passValue_b = document.getElementById('#{cc.attrs.id}:userText_b');

    objUserText_e.value = objUserText_b.value;
    passValue_e.value = passValue_b.value;

    /*
    copyValue('userText_b', 'userText_e'); copyValue('passValue_b', 'passValue_e');
    */

    // remove any return false
    // it will prevent the default event to be triggered (actionListener in this case)

}

i think this will submit the values without problems in the mobile version.

By the way, why duplicate the value of the inputs in the _e variables? can't you use the original _b ones? there are a lot of duplications sorry if i'm not getting why you do them.

SIDENOTE:

the same goes for the other form of id "login"

in the onClick event, just perform one action. multiple actions are not peformed by some browsers, so, insted of:

            <h:commandButton 
                class="btn" 
                value="Sign in"
                onclick="copyValue('userText_a', 'userText'); copyValue('passValue_a', 'passValue');"
                actionListener="#{cc.attrs.loginAction}"
            />

do this:

            <h:commandButton 
                class="btn" 
                value="Sign in"
                onclick="submit()"
                actionListener="#{cc.attrs.loginAction}"
            />

and you can perform the copyValue thing inside submit function:

function submit()
{
    copyValue('userText_a', 'userText');
    copyValue('passValue_a', 'passValue');
}

this way you will get the most cross-broser compatible code possible.

and again, try avoiding copyValue if possible. cheers

Devol answered 20/1, 2013 at 14:38 Comment(4)
Thanks for the response--I'll give this a shot. The reason for the copied values is that when there's a failure to log in an error message is displayed--unfortunately because of two competing models (Bootstrap and JSF2) the "simple" way for me to have three options in the same slot was swapping out the forms: e.g. -> <h:form class="navbar-form pull-right" id="login_error" prependId="false" rendered="#{cc.attrs.error and !cc.attrs.loggedIn} (This explains the duplicates as the forms would have colliding IDs, I had to duplicate somewhere). I'll give it another shot.Cherimoya
The project I was working on for this is dead, but I'll recreate it here in the next week or two on a little bootstrap project that's coming back to life. (I really want to solve this on--thanks for the response)Cherimoya
cool, just let me know if you still have this issue. try setting only one function in the onClick event and move everything inside (as in the "SIDENOTE" section of my answer). i think that may be the problem.Devol
Sorry for the ridiculously late response on this one. A dead project means I never have a chance to get back to it. What you suggested (essentially) works. I refactored a bit differently, but upon review this would definitely solve it. Great advice--much appreciated.Cherimoya

© 2022 - 2024 — McMap. All rights reserved.