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".
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With