我正在创建具有可滚动内容的列表框式小部件(溢出:滚动)。 可以通过鼠标悬停或键盘(使用向上/向下箭头)选择任何项目。
问题是:
当按键盘选择项目时,必须将新选择的项目滚动到视图中。由于该滚动,项目在鼠标光标下移动,这会带来不必要的鼠标事件。
如何在滚动浏览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”(滚动后删除标记),并在每次设置标志时忽略鼠标事件。 这不起作用 - 在鼠标事件发生时,标志从未设置过。
答案 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事件!