【问题标题】:Google Chrome Mobile (Nexus 7) | Form submission not working谷歌 Chrome 移动版 (Nexus 7) |表单提交不起作用
【发布时间】:2012-11-07 21:14:32
【问题描述】:

我在登录我的网站时遇到问题,该问题在移动 chrome 浏览器中显示(但适用于某些手机中提供的 web-kit 浏览器)。我正在努力尝试在平板电脑上进入“开发人员模式”,但我希望其他人已经遇到了这个问题,并且可以在我弄清楚如何实际调试时为我指出正确的方向。

它是一个 JSF2 应用程序(基于 Bootstrap2.2 的 Primefaces)作为 UI。

我的表单看起来像这样(第二组 'onblur' 调用是有意查看是否有帮助 - 它没有):

<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>

需要明确的是,我可以使用 Chrome/IE8+/Firefox/Opera 和移动设备登录桌面我只有 Chrome 的问题(我还没有尝试过 iOS 浏览器)。密码提交不会复制到帖子之前隐藏输入的值。

这可能不是最好的设计,我愿意接受建议。拖入 &lt;h:inputText /&gt; 组件会使样式复杂化,因为我已经在 Primefaces/Bootstrap 上大量回复并搞砸了布局,因此这是“解决方法”。

【问题讨论】:

  • 你能确认它是移动 chrome 浏览器和默认的 android 浏览器(常见的误解 - 默认浏览器不是 Chrome)吗?
  • 哦,肯定是 Chrome,默认浏览器(SlimBean 的浏览器)运行良好。
  • 我应该注意,我是在手机上运行 SlimBean,而不是在 Nexus 7 上运行,并且 Chrome 在 SlimBean 设备上也失败了。默认浏览器可在此设备上运行,Chrome 不能。

标签: javascript jsf-2 twitter-bootstrap primefaces composite-component


【解决方案1】:

而不是

            <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');"
            />

尽量不要在用户名和密码输入中设置 onblur 属性,因为 onBlur 属性在手机中可能会变得棘手。

相反,尝试在 onClick 事件中执行所有操作。我会在一个函数中做所有事情:

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

在函数内部:

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)

}

我认为这将在移动版本中毫无问题地提交值。

顺便说一句,为什么要在 _e 变量中重复输入的值?你不能用原来的 _b 吗?如果我不明白你为什么这样做,有很多重复。

旁注:

其他形式的 id "login" 也是如此

在 onClick 事件中,只需执行一项操作。某些浏览器不执行多个操作,因此,插入:

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

这样做:

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

你可以在提交函数中执行 copyValue 的事情:

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

这样您将获得尽可能多的跨浏览器兼容代码。

再一次,尽可能避免使用 copyValue。干杯

【讨论】:

  • 感谢您的回复——我会试一试。复制值的原因是,当登录失败时会显示错误消息——不幸的是,由于两个竞争模型(Bootstrap 和 JSF2),我在同一个插槽中拥有三个选项的“简单”方式是交换出表格:例如-> &lt;h:form class="navbar-form pull-right" id="login_error" prependId="false" rendered="#{cc.attrs.error and !cc.attrs.loggedIn}(这解释了重复项,因为表单会有冲突的 ID,我必须在某处复制)。我再试一次。
  • 我为此工作的项目已经死了,但我会在接下来的一两周内在一个小引导项目上重新创建它,该项目正在恢复生机。 (我真的很想解决这个问题——感谢您的回复)
  • 很酷,如果您还有这个问题,请告诉我。尝试在 onClick 事件中只设置一个函数并将所有内容移动到里面(如我答案的“SIDENOTE”部分)。我认为这可能是问题所在。
  • 抱歉,对这个问题的回复太晚了。一个死掉的项目意味着我永远没有机会重新开始它。您的建议(基本上)有效。我进行了一些不同的重构,但经过审查,这肯定会解决它。很好的建议——非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多