代码之家  ›  专栏  ›  技术社区  ›  Joeytje50

为什么在Chrome[复制]中使用preventDefault将<select multiple>框滚动到顶部

  •  1
  • Joeytje50  · 技术社区  · 8 年前

    每次我添加一个事件列表器时 preventDefault 更改选择框时,它会滚动到顶部。

    有关最简单的示例,请参见以下内容:

    document.getElementById('foo').onmousedown = function(e) {
      e.target.parentElement.focus();
      e.target.selected = !e.target.selected;
      e.preventDefault();
      return false;
    }
    <select multiple size="5" id="foo">
    <option>1</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
    <option>5</option>
    <option>6</option>
    <option>7</option>
    <option>8</option>
    <option>9</option>
    <option>10</option>
    </select>

    重现这种奇怪行为的步骤是:

    1. 单击选项 2
    2. 向下滚动一点
    3. 单击任意选项元素

    您的视图现在应该已向上滚动以具有选项 2. 在最顶端。

    我觉得这种行为很奇怪,真的很讨厌。

    接下来的问题是:我如何才能阻止这种情况发生?我想写一个剧本 select multiple 框的行为就像总是按ctrl键一样(请参见 https://stackoverflow.com/a/48217702/1256925 )但当 size 大于列出的选项数量。

    编辑 :我在MS Edge中测试过它(我在这台电脑上没有Firefox),它似乎能正确处理这个问题,所以这可能是一个Chrome特有的bug。如果是这样,我的后续问题仍然是:如何防止Chrome这样做?(还有,有没有人能告诉我这是否也发生在FF中?)

    1 回复  |  直到 8 年前
        1
  •  1
  •   bigless    8 年前

    尝试此解决方法(至少在Chrome中可用):

    document.getElementById('foo').onmousedown = function(e) {
      e.preventDefault();
      var st = this.scrollTop;
      e.target.selected = !e.target.selected;
      setTimeout(() => this.scrollTop = st, 0);
      this.focus();
    }
    
    document.getElementById('foo').onmousemove= function(e) {
        e.preventDefault();
    }
    <select multiple size="5" id="foo">
    <option>1</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
    <option>5</option>
    <option>6</option>
    <option>7</option>
    <option>8</option>
    <option>9</option>
    <option>10</option>
    </select>