防止页面在焦点切换时滚动

时间:2012-10-06 08:13:50

标签: javascript html cordova jquery-mobile webview

我是移动网络/开发新手。我的应用程序使用jquery-mobile,phonegap和Compass(s​​css)。

我的登录页面出现问题:

徽标和字段包含在标准“div”容器中(data-role =“content”data-type =“vertical”)。背景是彩色的。

将焦点从登录字段切换到密码字段时,页面会向上滑动,这是我不想发生的事情。我希望我的徽标和字段保持不变,就像Skype iOS App登录页面一样。

这是发生的事情:

bug description

我尝试了几种技巧,尝试阻止滚动事件,或强制页面滚动到0,0,但没有成功。

我正在考虑一个新的策略,可能使用徽标和字段的顶级相对定位,以及捕捉焦点事件以自己滚动页面,在键盘上滑动(通过设置顶部相对定位坐标)。

虽然这似乎可行,但我想知道这是否是Skype iOS App团队使用的那种工作......

欢迎任何有关此特殊情况的技术建议!

欢呼声,

佛瑞德

5 个答案:

答案 0 :(得分:10)

我认为您希望直接关注元素并使用' preventScroll'选项。

el.focus({preventScroll: true});

$('#el').focus((e) => {
  e.preventDefault();
  e.target.focus({preventScroll: true});
})

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus

答案 1 :(得分:4)

我还没有测试过,但e.preventDefault()是否会阻止这个问题?通常,您使用e.preventDefault()来停止默认的滚动/拖动行为。

$(document).bind('focus', function(e){
  e.preventDefault();
});

或更好

$(element).bind('focus', function(e){
  e.preventDefault();
});

$(document).bind('touchstart', function(e){
  e.preventDefault();
});

输入字段会更好吗?

$(":input").live({
  focus: function(e) {
    e.preventDefault();
  }
});

答案 2 :(得分:1)

我最终没有成功找到任何编码解决方案来处理我的问题,但我注意到一个手绘定位让我在切换字段时屏蔽了屏幕。

整个登录屏幕的可用空间不得超过键盘可见的可用空间,即200像素。此外,为防止切换字段时滚动,最后输入字段中心位置最大不得超过100个像素。使用CSS可以在填充和边距上播放以获得所需的结果。

通过删除键盘“字段导航栏”应该可以获得额外的垂直空间,但我不知道如何做到这一点:/

enter image description here

答案 3 :(得分:0)

我遇到了类似的问题(页面在单击/焦点上滚动),花了我一段时间才找到解决方案,所以我在这里进行了记录。

我有一个自定义表单字段,单击该字段时会将页面滚动到顶部。原来使用position: absolute; top: -99999999px;隐藏了输入(因为如果正确隐藏了输入,则焦点事件将不起作用)。这将隐藏的输入放置在页面顶部。然后,当我们单击标签并使输入聚焦时,页面将滚动到顶部。

我正在搜索诸如“滚动到焦点/单击顶部”之类的东西,但是找不到任何合适的东西。解决方案是改用right: -99999999px。我避免使用典型的left: -9999999px,因为使用direction: rtl;

显然会影响网站

答案 4 :(得分:0)

focus() 有一个 preventScroll 选项:
el.focus({preventScroll: true});

如果您必须支持不支持焦点选项的浏览器(IE11、Safari<14?),请使用此polyfill

!function(){

    let supported = false;
    document.createElement('i').focus({
        get preventScroll() {
            supported = true;
        },
    });
    if (!supported) {
        let original = HTMLElement.prototype.focus;
        Element.prototype.focus = HTMLElement.prototype.focus = function(options){
            if (options.preventScroll) {
                const map = new Map();
                let p = this;
                while (p = p.parentNode) map.set(p, [p.scrollLeft, p.scrollTop]);
                original.apply(this, arguments);
                map.forEach(function(pos, el){
                    // todo: test: only if changed? does it trigger scroll?
                    // IE flickers
                    el.scrollLeft = pos[0]
                    el.scrollTop  = pos[1]
                });
            } else {
                original.apply(this, arguments);
            }
        }
    }

}();