javascript - 通过 javascript 滚动内容时不需要的鼠标事件

标签 javascript

我正在创建具有可滚动内容(溢出:滚动)的类似列表框的小部件。 可以通过鼠标悬停或键盘(使用向上/向下箭头)选择任何项目。

问题是:

当通过键盘选择项目时,新选择的项目必须滚动到 View 中。由于该滚动,项目在鼠标光标下移动,这会带来不需要的鼠标事件。

如何防止项目在通过 scrollIntoView(或类似)滚动时获取鼠标事件?

var VK_DOWN = 40;


$('#scrollable div').mouseenter(function() {
  $(this).addClass('selected');
});

$('#scrollable div').mouseleave(function() {
  $(this).removeClass('selected');
});




$(document).keydown(function(e) {
  if (e.which == VK_DOWN) {
    e.preventDefault();

    //select next item
    var selected = $('div.selected');
    selected.removeClass('selected');
    selected = selected.next().addClass('selected');

    //scroll to selected item (if necessary)
    if (selected.position().top + 20 > 300) {
      selected[0].scrollIntoView(false);
    }


  } //vk_down
});
#scrollable {
  height: 300px;
  overflow: scroll;
  overflow-x: hidden;
}
#scrollable div {
  background: lightgray;
  border-bottom:2px solid white;
  height: 20px;
  cursor: default;
}
.selected {
  background: red !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="scrollable">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11 click this item, then press "down arrow" few times.</div>
  <div>12</div>
  <div>13</div>
  <div>14</div>
  <div>15</div>
  <div>16</div>
  <div>17</div>
  <div>18</div>
  <div>19</div>
  <div>20</div>
  <div>21</div>
  <div>22</div>
  <div>23</div>
  <div>24</div>
  <div>25</div>
  <div>26</div>
  <div>27</div>
  <div>28</div>
  <div>29</div>
  <div>30</div>
  <div>31</div>
  <div>32</div>
  <div>33</div>
  <div>34</div>
  <div>35</div>
  <div>36</div>
  <div>37</div>
  <div>38</div>
  <div>39</div>
  <div>40</div>
</div>

http://jsfiddle.net/sck0cbjn/1/

我的第一个想法是在 scrollIntoView() 之前设置标志“ItsMeScrolling”(滚动后删除标志),并在每次设置标志时忽略鼠标事件。 这没有用 - 在鼠标事件发生时,标志从未设置。

最佳答案

解决方案非常简单:

如果鼠标事件是有意的,鼠标光标会移动。 所以如果我们得到一个没有光标移动的事件,它必须是由滚动引起的。

http://jsfiddle.net/sck0cbjn/7/

var VK_DOWN = 40;
var lastCursorPos = {
  x: 0,
  y: 0
};


$('#scrollable div').mousemove(function(e) {
  var currentCursorPos = {
    x: e.screenX,
    y: e.screenY
  };

  if (currentCursorPos.x == lastCursorPos.x &&
    currentCursorPos.y == lastCursorPos.y) {
    console.log("cursor didn't move so this event was not intended.");
    return;
  }
  lastCursorPos = {
    x: e.screenX,
    y: e.screenY
  };

  $('#scrollable div').removeClass('selected');
  $(this).addClass('selected');
});

$('#scrollable div').mouseleave(function(e) {
  $(this).removeClass('selected');
  lastCursorPos = {
    x: e.screenX,
    y: e.screenY
  };
});




$(document).keydown(function(e) {
  if (e.which == VK_DOWN) {
    e.preventDefault();

    //select next item
    var selected = $('div.selected');
    selected.removeClass('selected');
    selected = selected.next().addClass('selected');

    //scroll to selected item (if necessary)
    if (selected.position().top + 20 > 300) {
      selected[0].scrollIntoView(false);
    }

  } //vk_down
});
#scrollable {
  height: 300px;
  overflow: scroll;
  overflow-x: hidden;
}
#scrollable div {
  background: lightgray;
  border-bottom: 2px solid white;
  height: 20px;
  cursor: default;
}
.selected {
  background: red !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="scrollable">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11 click this item, then press "down arrow" few times.</div>
  <div>12</div>
  <div>13</div>
  <div>14</div>
  <div>15</div>
  <div>16</div>
  <div>17</div>
  <div>18</div>
  <div>19</div>
  <div>20</div>
  <div>21</div>
  <div>22</div>
  <div>23</div>
  <div>24</div>
  <div>25</div>
  <div>26</div>
  <div>27</div>
  <div>28</div>
  <div>29</div>
  <div>30</div>
  <div>31</div>
  <div>32</div>
  <div>33</div>
  <div>34</div>
  <div>35</div>
  <div>36</div>
  <div>37</div>
  <div>38</div>
  <div>39</div>
  <div>40</div>
</div>

当心: 将光标从一个元素移动到另一个元素(之间没有间隙)时,您将得到: mouseleave 和 mouseenter 事件具有相同的坐标!

关于javascript - 通过 javascript 滚动内容时不需要的鼠标事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26179043/

相关文章:

javascript - 将简单的 JSON 字符串转换为 JSON 对象

javascript - 在不丢失选择的情况下使用 JavaScript 更改选择中的选项

javascript - angularjs随 secret 码生成器至少一个大写小写数字和特殊字符

javascript - 将包含数组的对象键复数化

javascript - 我们如何在 javascript 类方法中传递参数

javascript - jQuery 的网站的演示窗口滚动是如何工作的?

javascript - 无法读取 null 的属性 'addEventListener'

javascript - 切换表格 <tr> 的显示 :none using Javascript

Javascript 全局与局部作用域

javascript - 尝试实现 Fittext.js