【问题标题】:focus() to input without scrollingfocus() 无需滚动即可输入
【发布时间】:2011-02-10 21:40:27
【问题描述】:

我有一个搜索输入文本,我想在加载页面时应用focus(),问题是focus 函数会自动滚动到该字段。有什么办法可以禁用这个滚动?

<input id="search_terms" type="text" />
<script>
    document.getelementbyId('search-terms').focus();
</script>

【问题讨论】:

  • 您想捕捉用户的击键而不他们看到他们正在输入的元素?
  • 你为什么认为这种滚动是个问题?
  • 加载后必须使用 JavaScript 设置滚动位置:window.scrollTo(x,y)
  • 我有一个应用程序正是需要这种行为。我有一个页面显示一年中连续三个月的数据。有下一个和上一个按钮可以更改您查看的三个月。当用户单击下一个或上一个时,我将光标重新聚焦在最后选择的输入上,允许用户跟踪他们的位置(如果他们正在输入数据或检查数字)。在这种情况下,滚动真的很刺耳,并且会阻止您反复按上一个/下一个按钮。
  • 这简直把我逼疯了。显然有一个选项可以传递给名为 preventScroll 的焦点:developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus

标签: javascript html scroll


【解决方案1】:

有一个新的WHATWG standard 允许您将一个对象传递给focus(),指定您希望阻止浏览器将元素滚动到视图中:

const element = document.getElementById('search-terms')

element.focus({
  preventScroll: true
});

Chrome 64Edge Insider Preview build 17046 以来一直支持它,并且应该登陆 Firefox 68 - web-platform-tests here 上提供了支持矩阵。

【讨论】:

【解决方案2】:

这是一个完整的解决方案:

var cursorFocus = function(elem) {
  var x = window.scrollX, y = window.scrollY;
  elem.focus();
  window.scrollTo(x, y);
}

cursorFocus(document.getElementById('search-terms'));

【讨论】:

  • 很好的解决方案,但是在 IE9 上的某些情况下,最好使用 setTimeout(function() { window.scrollTo(x, y); }, 100); 而不是 window.scrollTo(x, y);
  • window.scrollX 和 window.scrollY 不是跨浏览器保存,使用 document.body.scrollLeft 和 document.body.scrollTop
  • 它们适用于大多数现代浏览器 (IE9+),我认为这是合理的。
  • 当我这样做时,我仍然可以看到页面滚动到顶部,然后跳回保存的位置。有没有办法防止这种情况发生?
  • 您使用的是哪个浏览器?它可能会在响应编程事件之前为滚动设置动画
【解决方案3】:

如果你使用 jQuery,你也可以这样做:

$.fn.focusWithoutScrolling = function(){
  var x = window.scrollX, y = window.scrollY;
  this.focus();
  window.scrollTo(x, y);
};

然后

$('#search_terms').focusWithoutScrolling();

【讨论】:

  • 感谢您,但我发现需要将函数的第一行更改为 var x = $(document).scrollLeft(), y = $(document).scrollTop(); 才能使其在 IE10 中运行。
【解决方案4】:

这里的答案不关心滚动整个层次结构,而只关心主滚动条。这个答案将解决所有问题:

    var focusWithoutScrolling = function (el) {
        var scrollHierarchy = [];

        var parent = el.parentNode;
        while (parent) {
            scrollHierarchy.push([parent, parent.scrollLeft, parent.scrollTop]);
            parent = parent.parentNode;
        }

        el.focus();

        scrollHierarchy.forEach(function (item) {
            var el = item[0];

            // Check first to avoid triggering unnecessary `scroll` events

            if (el.scrollLeft != item[1])
                el.scrollLeft = item[1];

            if (el.scrollTop != item[2])
                el.scrollTop = item[2];
        });
    };

【讨论】:

    【解决方案5】:

    稍作修改,支持更多浏览器(包括IE9)

    var cursorFocus = function(elem) {
      var x, y;
      // More sources for scroll x, y offset.
      if (typeof(window.pageXOffset) !== 'undefined') {
          x = window.pageXOffset;
          y = window.pageYOffset;
      } else if (typeof(window.scrollX) !== 'undefined') {
          x = window.scrollX;
          y = window.scrollY;
      } else if (document.documentElement && typeof(document.documentElement.scrollLeft) !== 'undefined') {
          x = document.documentElement.scrollLeft;
          y = document.documentElement.scrollTop;
      } else {
          x = document.body.scrollLeft;
          y = document.body.scrollTop;
      }
    
      elem.focus();
    
      if (typeof x !== 'undefined') {
          // In some cases IE9 does not seem to catch instant scrollTo request.
          setTimeout(function() { window.scrollTo(x, y); }, 100);
      }
    }
    

    【讨论】:

      【解决方案6】:

      我有一个类似的问题让我发疯。使用 jQuery,我通过发现鼠标和输入的坐标然后滚动到它们之间的差异找到了一个解决方案。在你的情况下,它可能是这样的:

        document.addEventListener("mousemove", (e) => {
          mouseCoords = { x: e.clientX, y: e.clientY };
        });
      
        $('#search_terms').bind("focus", function (e) {
            var offset = e.offset();
            window.scrollTo(
              offset.left - mouseCoords.x,
              offset.top - mouseCoords.y
            );
        });
      

      【讨论】:

        【解决方案7】:

        到目前为止,在页面加载时将焦点设置在元素上的首选方法是使用 autofocus 属性。这不涉及任何滚动。

        &lt;input id="search_terms" type="text" autofocus /&gt;

        autofocus 属性is part of the HTML5 standard 受所有主流浏览器支持,唯一值得注意的例外是 Internet Explorer 9 或更早版本。

        【讨论】:

        • 我很高兴看到这种聚焦输入的现代方法,但它仍然“滚动”到聚焦输入框(至少在 Chrome 中)。例如,当您在 Chrome 中刷新页面时,它会重新加载页面,但会让您滚动到该页面上的同一部分。如果您在页面中间的输入上设置自动对焦,当您重新加载时,您现在将滚动以使输入垂直居中。我认为这个“滚动”是 OP 试图避免的。如果用户正在阅读一篇长文章,我们不希望他们在点击刷新时一直滚动到顶部的搜索框。
        猜你喜欢
        • 1970-01-01
        • 2015-02-19
        • 2023-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-03
        • 1970-01-01
        • 2018-07-31
        相关资源
        最近更新 更多