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

时间:2014-10-03 12:36:02

标签: javascript

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

问题是:

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

如何在滚动浏览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”(滚动后删除标记),并在每次设置标志时忽略鼠标事件。 这不起作用 - 在鼠标事件发生时,标志从未设置过。

1 个答案:

答案 0 :(得分:3)

解决方案非常简单:

如果想要鼠标事件,鼠标光标会移动。 因此,如果我们得到一个没有光标移动的事件,它必须由滚动引起。

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然后使用相同的coords进行mouseenter事件!