使用鼠标滚轮

时间:2016-08-22 21:30:55

标签: javascript google-chrome input javascript-events mousewheel

我正在尝试使用鼠标滚轮增加/减少输入字段的值。我把以下代码放在一起。它工作正常,但有一个小问题。

我想要的行为是,一旦我专注于元素,就可以使用鼠标滚轮增加/减少输入值。鼠标不必悬停在元素上。以下代码执行此操作。但是如果我在悬停输入元素时使用wheel,则值会增加/减少2而不是1。

var hoveredInput = null;

$('input[type="number"]').on("focus", function(e) {
  hoveredInput = this;
});
$('input[type="number"]').on("blur", function(e) {
  hoveredInput = null;
});

$(window).on("wheel", function(e) {
  if (hoveredInput) {
    if (e.originalEvent.deltaY < 0) {
      var currentValue = parseInt(hoveredInput.value, 10);
      var newValue = currentValue + 1;
      if (newValue > parseInt(hoveredInput.max, 10)) {
        newValue = hoveredInput.max;
      }
      hoveredInput.value = newValue;
    } else {
      var currentValue = parseInt(hoveredInput.value, 10);
      var newValue = currentValue - 1;
      if (newValue < parseInt(hoveredInput.min, 10)) {
        newValue = hoveredInput.min;
      }
      hoveredInput.value = newValue;
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" value="0" min="0" max="255" />

经过一些实验,我发现向上和向下箭头键有类似的行为。在数字输入上的向上和向下箭头键递增/递减该值。我想,这种行为与我的代码冲突。使它增加2,即使代码没有执行两次。

我刚刚意识到这可能是Chrome特有的问题。如果您对焦并悬停元素,Chrome可让您使用鼠标滚轮增加/减少数字输入值。但是,它的工作方式非常奇怪。

如果我只是在空白HTML页面中添加<input type="number" />,则此鼠标滚轮增量不起作用。为了使其有效,我只需添加window.onwheel = function() {};。这没有任何意义。此外,这似乎适用于JSFiddleonwheel上没有window分配的JSBin。

回到实际问题,我可以禁用元素上的默认鼠标滚轮增量,以便我可以使用我的自定义鼠标滚轮增量吗?或者我可以使用另一种方法吗?

1 个答案:

答案 0 :(得分:2)

我不确定为什么你会考虑使用preventDefault()来阻止默认操作。您正在更改在这些情况下UI操作的内容。当然,您应该使用preventDefault()来阻止默认操作。如果您不使用preventDefault(),那么在<input type="number">聚焦时使用滚轮会产生一些意想不到的后果。如果没有preventDefault(),在这些条件下会发生意外后果的组合将取决于用于查看页面的浏览器。

我无法使用光标键更改输入值来复制冲突。显然,如果您用来限制<input>的最小值和最大值是鼠标滚轮的代码,那么这些限制将不适用于任何其他进入方法。您可以使用minmax属性来限制值。这样做会因多种原因而更好,包括它会影响所有输入值的方法,因为它允许按<input>定义这些范围,而不是为所有<input type="number">定义一组限制。我已经更改了代码,以便您的代码也使用这些属性。

如果这样做,您可能需要考虑添加CSS样式以指示<input type="number">元素具有焦点。这样做将使用户更清楚地知道为什么鼠标滚轮没有按照他们通常期望的浏览器UI进行操作。

我建议您尝试使用多个浏览器来查看它是否是您想要的内容。就个人而言,至少在我在这个页面上做过的测试中,我喜欢这种行为。

注意:
您对focusblur事件的使用过于复杂。我已经使用document.activeElement更改了代码以直接找到焦点元素。

//Exclude one specific element for comparing this UI vs. the browser's default.
var excludedEl = document.getElementById('exclude');

$(window).on("wheel", function(e) {
  focusedEl = document.activeElement;
  if(focusedEl === excludedEl){
    //Exclude one specific element for UI comparison 
    return;
  }
  if (focusedEl.nodeName='input' && focusedEl.type && focusedEl.type.match(/number/i)){
    e.preventDefault();
    var max=null;
    var min=null;
    if(focusedEl.hasAttribute('max')){
      max = focusedEl.getAttribute('max');
    }
    if(focusedEl.hasAttribute('min')){
      min = focusedEl.getAttribute('min');
    }
    var value = parseInt(focusedEl.value, 10);
    if (e.originalEvent.deltaY < 0) {
      value++;
      if (max !== null && value > max) {
        value = max;
      }
    } else {
      value--;
      if (min !== null && value < min) {
        value = min;
      }
    }
    focusedEl.value = value;
  }
});
input[type="number"]:focus {
  box-shadow: 0px 0px 1.5px 1px cyan;
}

/*For comparing UIs: May conflict with browser default, or user's theme.*/
#exclude:focus {
  box-shadow: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
NOTE: Events are only caught while the mouse stays within the test portion of the stackoverflow page:<br/><br/><br/>

Uses changed UI (if focused, mouse wheel will increment/decrement):<br/>
<input type="number" value="0" id="firstNumberInput" min="0" max="255"/>
<br/>Uses browser default UI:
<input id="exclude" type="number" value="0" min="0" max="255" style="display:block"/>