Tắt cuộn trên `<input type = number> '


121

Có thể tắt con lăn thay đổi số trong trường số đầu vào không? Tôi đã làm rối với CSS dành riêng cho webkit để xóa spinner nhưng tôi muốn loại bỏ hoàn toàn hành vi này. Tôi thích sử dụng type=numbervì nó mang lại một bàn phím đẹp trên iOS.


7
sử dụng kiểu đầu vào tel (type = "tel") thay vì sử dụng type = number. Nó sẽ bật lên một bàn phím số iOS.
Praveen Vijayan

Điều gì xảy ra khi bạn thêm một onscrolltrình xử lý chỉ event.preventDefault()trong đó?
robertc

14
Theo ý kiến ​​khiêm tốn của tôi, tôi thậm chí không nghĩ đây phải là một tính năng. Nếu tôi có bất kỳ tiếng nói nào trong việc phát triển trình duyệt, tôi có thể sẽ thúc đẩy loại bỏ tính năng này. Nó không có gì nhưng khó chịu, và tôi không biết bất cứ ai thực sự sẽ sử dụng nó.
Kirkland

3
Tôi hoàn toàn đồng ý với bạn Kirkland. UX thật tệ khi cuộn một trang có biểu mẫu và khi một phần tử nhập số nằm dưới con chuột của bạn, nó bắt đầu tăng lên và trang ngừng cuộn. Hoàn toàn mất phương hướng.
kjs3

3
@PraveenVijayan: Mặc dù đây là một giải pháp thay thế, nhưng nó đi ngược lại bất kỳ lý do nào cho việc sử dụng các loại đầu vào html5 mới. Trong tương lai, có thể điện thoại sẽ cung cấp cho bạn khả năng chọn số từ danh bạ hoặc bất cứ thứ gì, điều này sẽ rất lạ nếu bạn muốn đây là một loại số khác.
awe

Câu trả lời:


92

Ngăn chặn hành vi mặc định của sự kiện con lăn chuột trên các phần tử đầu vào-số như được đề xuất bởi những người khác (gọi "dim ()" thường không phải là cách ưa thích để làm điều đó, vì đó sẽ không phải là điều người dùng muốn).

NHƯNG. Tôi sẽ tránh lắng nghe sự kiện con lăn chuột trên tất cả các phần tử đầu vào-số mọi lúc và chỉ làm điều đó, khi phần tử được lấy nét (đó là khi vấn đề tồn tại). Nếu không , người dùng không thể cuộn trang khi con trỏ chuột ở bất kỳ đâu trên phần tử nhập-số.

Giải pháp cho jQuery:

// disable mousewheel on a input number field when in focus
// (to prevent Cromium browsers change the value when scrolling)
$('form').on('focus', 'input[type=number]', function (e) {
  $(this).on('wheel.disableScroll', function (e) {
    e.preventDefault()
  })
})
$('form').on('blur', 'input[type=number]', function (e) {
  $(this).off('wheel.disableScroll')
})

(Ủy quyền các sự kiện tiêu điểm cho phần tử biểu mẫu xung quanh - để tránh cho nhiều người nghe sự kiện, điều này không tốt cho hiệu suất.)


2
Câu trả lời chính xác. Tôi nghĩ nếu tôi làm điều này hôm nay, tôi sẽ sử dụng Modernizr.touch để áp dụng có điều kiện trình xử lý sự kiện trên các thiết bị không cảm ứng. Về cơ bản những gì user2863715 nói bên dưới.
kjs3

Câu trả lời tuyệt vời, nhưng ít nhất trong webkit, điều này cũng ngăn cửa sổ cuộn trong khi con trỏ ở trên phần tử đầu vào. Tôi nghĩ rằng sự kiện con lăn chuột cũng được cho là bong bóng.
Ryan McGeary

Khi chỉ áp dụng chức năng vô hiệu hóa cuộn cho một phần tử khi nó nằm trong tiêu điểm, điều này sẽ không ngăn cản việc cuộn khi con chuột ở trên phần tử đầu vào. Nhưng nó ngăn không cho cuộn cửa sổ khi phần tử được lấy nét. Và vâng, tại sao sự kiện mousewheel không sủi bọt ...: /
Grantzau

6
Đây là một bản sửa lỗi tốt cho một hành vi không nên tồn tại ngay từ đầu.
Jonny

Điều này không hoạt động trên hầu hết các nền tảng loại unix gnome, osx, android (với chuột) vì hành vi cuộn không yêu cầu đầu vào phải được tập trung. Ngoài ra, tôi chỉ sử dụng các loại văn bản của đầu vào và đặt hạn chế số của tôi với nó (lossing lên / xuống phím tắt nhưng có thể được thêm vào với js cũng)
zeachco

40
$(document).on("wheel", "input[type=number]", function (e) {
    $(this).blur();
});

2
đây là một trong đó là hoàn hảo.
Patrik Laszlo

Nó hoạt động tốt. Cảm ơn bạn.
Vijay S

20

Một người nghe sự kiện để thống trị tất cả

Điều này tương tự như câu trả lời của @Simon Perepelitsa trong js thuần túy, nhưng đơn giản hơn một chút, vì nó đặt một trình xử lý sự kiện vào phần tử tài liệu và kiểm tra xem phần tử tập trung có phải là đầu vào số hay không:

document.addEventListener("wheel", function(event){
    if(document.activeElement.type === "number"){
        document.activeElement.blur();
    }
});

Nếu bạn muốn tắt hành vi cuộn giá trị trên một số trường, nhưng không phải những trường khác, chỉ cần làm điều này thay thế:

document.addEventListener("wheel", function(event){
    if(document.activeElement.type === "number" &&
       document.activeElement.classList.contains("noscroll"))
    {
        document.activeElement.blur();
    }
});

Với cái này:

<input type="number" class="noscroll"/>

Nếu một đầu vào có lớp noscroll thì nó sẽ không thay đổi khi cuộn, nếu không thì mọi thứ vẫn như cũ.

Kiểm tra ở đây với JSFiddle


Tôi thấy điều này đã bị phản đối. Nếu bạn thấy một vấn đề, xin vui lòng để lại một bình luận cũng như với downvote. Nếu tôi bỏ lỡ điều gì đó, tôi muốn tìm hiểu nó là gì. Cảm ơn.
Peter Rakmanyi

1
Đối với trình duyệt hiện đại, vui lòng sử dụng sự kiện wheelthay vì mousewheel. Tham khảo: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event PS. Tôi không phải là người bỏ phiếu.
vee

19
input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(event){ this.blur() })

http://jsfiddle.net/bQbDm/2/

Đối với ví dụ về jQuery và giải pháp đa trình duyệt, hãy xem câu hỏi liên quan:

Trình xử lý sự kiện HTML5 cho cuộn nhập số - Chỉ Chrome


2
Cảm ơn Seymon, tôi đã quản lý để làm điều đó cho tất cả các đầu vào số với jQuery theo cách này: $(':input[type=number]' ).live('mousewheel',function(e){ $(this).blur(); });Tôi đã sử dụng làm mờ thay vì ngăn chặn mặc định để nó không chặn trang cuộn!
Thibaut Colson

Bổ sung tốt về độ mờ, tôi không biết bạn vẫn có thể cho phép cuộn trang. Tôi đã cập nhật câu trả lời của mình.
Simon Perepelitsa

13
FYI, live()không được dùng nữa. Bây giờ, bạn nên sử dụng on(): $(':input[type=number]').on('mousewheel',function(e){ $(this).blur(); });
Saeid Zebardast

3
@SaeidZebardast Nhận xét của bạn xứng đáng là câu trả lời
snumpy

Đối với trình duyệt hiện đại, vui lòng sử dụng sự kiện wheelthay vì mousewheel. Tham khảo: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

16

Bạn chỉ cần sử dụng thuộc tính onwheel HTML .

Tùy chọn này không ảnh hưởng đến việc cuộn qua các phần tử khác của trang.

Và thêm trình lắng nghe cho tất cả các đầu vào không hoạt động trong các đầu vào được tạo động sau đó.

Tùy ý, bạn có thể loại bỏ các mũi tên đầu vào bằng CSS.

input[type="number"]::-webkit-outer-spin-button, 
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
}
<input type="number" onwheel="this.blur()" />


1
Cảm ơn nhé người anh em!! nó làm việc hoàn hảo trong góc - Material 6
Nasiruddin Saiyed


Chúng ta có thể tìm thấy CSS này ở nhiều nguồn. Dù sao, CSS chỉ là một phần thưởng. Giải pháp thực sự cho câu hỏi là thuộc tính onwheel HTML. ;-)
Maikon Matheus

5
Tôi thích giải pháp này! Cảm ơn. Trong trường hợp của tôi, onBlur()không như mong đợi. return falseThay vào đó, tôi thiết lập một đơn giản để thực sự "không làm gì trên tay lái". <input type="number" onwheel="return false;">
Daniel

14

@Semyon Perepelitsa

Có một giải pháp tốt hơn cho điều này. Blur xóa tiêu điểm khỏi đầu vào và đó là một ảnh hưởng phụ mà bạn không muốn. Bạn nên sử dụng evt.preventDefault thay thế. Điều này ngăn chặn hành vi mặc định của đầu vào khi người dùng cuộn. Đây là mã:

input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(evt){ evt.preventDefault(); })

6
Nó hoạt động, nhưng sự kiện sẽ không bong bóng, vì vậy trang sẽ không cuộn. Có cách nào để giữ hành vi mặc định (cuộn trang) mà không bị mờ không?
GuiGS

Đối với trình duyệt hiện đại, vui lòng sử dụng sự kiện wheelthay vì mousewheel. Tham khảo: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

7

Trước tiên, bạn phải dừng sự kiện con lăn chuột bằng cách:

  1. Vô hiệu hóa nó bằng mousewheel.disableScroll
  2. Chặn nó bằng e.preventDefault();
  3. Bằng cách xóa tiêu điểm khỏi phần tử el.blur();

Hai cách tiếp cận đầu tiên đều ngăn cửa sổ cuộn và cách cuối cùng loại bỏ tiêu điểm khỏi phần tử; cả hai đều là kết quả không mong muốn.

Một cách giải quyết là sử dụng el.blur()và lấy nét lại phần tử sau một khoảng thời gian trễ:

$('input[type=number]').on('mousewheel', function(){
  var el = $(this);
  el.blur();
  setTimeout(function(){
    el.focus();
  }, 10);
});

3
Một giải pháp đẹp mắt, nhưng trong quá trình thử nghiệm, tôi thấy rằng giải pháp này có tác dụng phụ là đánh cắp tiêu điểm. Tôi đã chỉnh sửa điều này để có: kiểm tra xem phần tử có tiêu điểm hay không: var hadFocus = el.is(':focus');trước khi làm mờ và sau đó là một trình bảo vệ để chỉ đặt thời gian chờ nếu hadFocs là true.
Rob Dawson

2

Các câu trả lời được cung cấp không hoạt động trong Firefox (Lượng tử). Trình nghe sự kiện cần được thay đổi từ con lăn chuột sang bánh xe:

$(':input[type=number]').on('wheel',function(e){ $(this).blur(); });

Mã này hoạt động trên Firefox Quantum và Chrome.


2

Dành cho bất kỳ ai làm việc với React và đang tìm kiếm giải pháp. Tôi đã phát hiện ra rằng cách dễ nhất là sử dụng onWheelCapture prop trong thành phần Đầu vào như sau:

onWheelCapture={e => { e.target.blur() }}


2

Biến thể chỉ số

Typecript cần biết rằng bạn đang làm việc với HTMLElement để đảm bảo an toàn cho kiểu, nếu không bạn sẽ thấy rất nhiều Property 'type' does not exist on type 'Element'loại lỗi.

document.addEventListener("mousewheel", function(event){
  let numberInput = (<HTMLInputElement>document.activeElement);
  if (numberInput.type === "number") {
    numberInput.blur();
  }
});

1

Trong khi cố gắng giải quyết vấn đề này cho chính mình, tôi nhận thấy rằng thực sự có thể giữ lại cuộn trang và tiêu điểm của đầu vào trong khi vô hiệu hóa các thay đổi số bằng cách cố gắng kích hoạt lại sự kiện đã bắt trên phần tử chính của <input type="number"/>nó. , đơn giản như thế này:

e.target.parentElement.dispatchEvent(e);

Tuy nhiên, điều này gây ra lỗi trong bảng điều khiển trình duyệt và có lẽ không được đảm bảo hoạt động ở mọi nơi (tôi chỉ thử nghiệm trên Firefox), vì đó là mã cố ý không hợp lệ.

Một giải pháp khác hoạt động tốt ít nhất là trên Firefox và Chromium là tạm thời tạo <input>phần tử readOnly, như sau:

function handleScroll(e) {
  if (e.target.tagName.toLowerCase() === 'input'
    && (e.target.type === 'number')
    && (e.target === document.activeElement)
    && !e.target.readOnly
  ) {
      e.target.readOnly = true;
      setTimeout(function(el){ el.readOnly = false; }, 0, e.target);
  }
}
document.addEventListener('wheel', function(e){ handleScroll(e); });

Một tác dụng phụ mà tôi nhận thấy là nó có thể khiến trường nhấp nháy trong tích tắc nếu bạn có kiểu khác nhau cho readOnlycác trường, nhưng ít nhất đối với trường hợp của tôi, điều này dường như không phải là vấn đề.

Tương tự, (như được giải thích trong câu trả lời của James) thay vì sửa đổi readOnly tính, bạn có thể blur()điền và sau focus()đó quay lại trường, nhưng một lần nữa, tùy thuộc vào kiểu được sử dụng, một số hiện tượng nhấp nháy có thể xảy ra.

Ngoài ra, như đã đề cập trong các nhận xét khác ở đây, bạn có thể chỉ cần gọi điện preventDefault()về sự kiện. Giả sử rằng bạn chỉ xử lý wheelcác sự kiện trên đầu vào số nằm trong tiêu điểm và dưới con trỏ chuột (đó là điều mà ba điều kiện ở trên biểu thị), tác động tiêu cực đến trải nghiệm người dùng sẽ gần như không có.


1

Nếu bạn muốn một giải pháp không cần JavaScript, việc kết hợp một số chức năng HTML với một phần tử giả CSS sẽ thực hiện thủ thuật:

span {
  position: relative;
  display: inline-block; /* Fit around contents */
}

span::after {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0; /* Stretch over containing block */
  cursor: text; /* restore I-beam cursor */
}

/* Restore context menu while editing */
input:focus {
  position: relative;
  z-index: 1;
}
<label>How many javascripts can u fit in u mouth?
  <span><input type="number" min="0" max="99" value="1"></span>
</label>

Điều này hoạt động bởi vì nhấp vào nội dung của <label> liên kết với một trường biểu mẫu sẽ làm tiêu điểm trường. Tuy nhiên, “khung cửa sổ” của phần tử giả trên trường sẽ chặn các sự kiện con lăn chuột tiếp cận nó.

Hạn chế là các nút xoay lên / xuống không còn hoạt động, nhưng bạn cho biết dù sao thì bạn cũng đã loại bỏ chúng.


Về lý thuyết, người ta có thể khôi phục menu ngữ cảnh mà không yêu cầu đầu vào phải được tập trung trước: các :hoverkiểu không được kích hoạt khi người dùng cuộn, vì các trình duyệt tránh tính toán lại chúng trong quá trình cuộn vì lý do hiệu suất, nhưng tôi chưa thực sự duyệt qua nhiều trình duyệt / thiết bị đã thử nghiệm nó.


0
function fixNumericScrolling() {
$$( "input[type=number]" ).addEvent( "mousewheel", function(e) {
    stopAll(e);     
} );
}

function stopAll(e) {
if( typeof( e.preventDefault               ) != "undefined" ) e.preventDefault();
if( typeof( e.stopImmediatePropagation     ) != "undefined" ) e.stopImmediatePropagation();
if( typeof( event ) != "undefined" ) {
    if( typeof( event.preventDefault           ) != "undefined" ) event.preventDefault();
    if( typeof( event.stopImmediatePropagation ) != "undefined" ) event.stopImmediatePropagation();
}

return false;
}

0

Giải pháp dễ nhất là thêm onWheel={ event => event.currentTarget.blur() }}đầu vào chính nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.