"<İnput type = number>" üzerinde kaydırmayı devre dışı bırakın


121

Bir giriş numarası alanındaki numarayı değiştirerek kaydırma tekerleğini devre dışı bırakmak mümkün müdür? Spinner'ı kaldırmak için webkit'e özgü CSS ile uğraştım, ancak bu davranıştan tamamen kurtulmak istiyorum. type=numberİOS'ta güzel bir klavye getirdiği için kullanmayı seviyorum .


7
tür = sayı kullanmak yerine giriş türü tel (tür = "tel") kullanın. Bir iOS num klavyesi açılır.
Praveen Vijayan

onscrollSadece event.preventDefault()içinde olan bir işleyici eklediğinizde ne olur ?
robertc

14
Alçakgönüllü görüşüme göre, bunun bir özellik olması gerektiğini bile düşünmüyorum. Tarayıcı geliştirme konusunda herhangi bir sözüm olsaydı, muhtemelen bu özelliği kaldırmak için zorlardım. Bu sinir bozucudan başka bir şey değil ve onu gerçekten kullanacak birini tanımıyorum.
Kirkland

3
Sana tamamen katılıyorum Kirkland. Bir form içeren bir sayfayı kaydırmak kötü kullanıcı deneyimi ve bir sayı giriş öğesi farenizin altına girdiğinde, artmaya başlar ve sayfa kaydırmayı durdurur. Tamamen kafa karıştırıcı.
kjs3

3
@PraveenVijayan: Bu bir geçici çözüm olmasına rağmen, yeni html5 giriş türlerini kullanmak için herhangi bir nedene aykırıdır. Gelecekte, telefonlar size kişilerden numara seçme veya herhangi bir şey yapma olanağı sunabilir, eğer bunun farklı bir tür olmasını istediyseniz, bu çok garip görünecektir.
korku

Yanıtlar:


92

Başkalarının önerdiği gibi fare tekerleği olayının giriş numarası öğelerinde varsayılan davranışını önleyin (normalde bunu yapmanın tercih edilen yolu "blur ()" değildir, çünkü kullanıcının istediği bu değildir).

FAKAT. Fare tekerleği olayını her zaman tüm girdi numarası öğelerinde dinlemekten kaçınırdım ve bunu yalnızca öğe odakta olduğunda (sorun var olduğunda) yaparım. Aksi takdirde , fare imleci bir giriş numarası öğesinin üzerinde herhangi bir yerde olduğunda kullanıcı sayfayı kaydıramaz.

JQuery için çözüm:

// 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')
})

(Performans için kötü olan birçok olay dinleyicisinden kaçınmak için odak olaylarını çevreleyen form öğesine delege edin.)


2
Mükemmel cevap. Sanırım bugün bunu yapıyor olsaydım, olay dinleyicisini koşullu olarak dokunmatik olmayan cihazlara uygulamak için Modernizr.touch'u kullanırdım. Kullanıcı2863715'in aşağıda söylediği temelde.
kjs3

Harika yanıt, ancak en azından webkit'te bu, imleç giriş öğesinin üzerindeyken pencerenin kaymasını da engeller. Fare tekerleği olaylarının da köpürmesi gerektiğini düşündüm.
Ryan McGeary

Kaydırmayı devre dışı bırak işlevini yalnızca odakta olan bir öğeye uygularken, bu, fare giriş öğesinin üzerindeyken kaydırmayı engellememelidir. Ancak, öğe odakta olduğunda pencerenin kaydırılmasını engeller. Ve evet, fare tekerleği olayı neden
köpürmüyor

6
Bu, ilk etapta var olmaması gereken bir davranış için güzel bir düzeltme.
Jonny

Kaydırma davranışı girdinin odaklanmasını gerektirmediğinden, bu çoğu unix tipi platform gnome, osx, android (fare ile) üzerinde çalışmaz. Alternatif olarak, sadece metin türü girdileri kullandım ve sayı kısıtlamamı buna koydum (yukarı / aşağı tuş kısayolunu
kaybederek

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

2
bu mükemmel olanı.
Patrik Laszlo

İyi Çalışıyor. Teşekkür ederim.
Vijay S

21

Hepsini yönetecek bir olay dinleyicisi

Bu benzer @Simon Perepelitsa 'ın cevabı saf js, ancak odaklanmış eleman bir numara girişi ise o belge elemanı ve çeklerde bir olay dinleyicisi koyar gibi bir basit bit:

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

Bazı alanlarda değer kaydırma davranışını kapatmak istiyor ancak diğerlerinde bunu yapmak istemiyorsanız bunu yapın:

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

Bununla:

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

Bir girdi noscroll sınıfına sahipse, kaydırmada değişmez, aksi takdirde her şey aynı kalır.

JSFiddle ile burada test edin


Bunun reddedildiğini görüyorum. Bir sorun görürseniz, lütfen olumsuz oyla birlikte bir yorum bırakın. Bir şeyi kaçırırsam ne olduğunu öğrenmek isterim. Teşekkürler.
Peter Rakmanyi

1
Modern tarayıcı için lütfen wheelyerine event kullanın mousewheel. Referans: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event PS. Olumsuz oy kullanan ben değilim.
vee

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

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

JQuery örneği ve tarayıcılar arası bir çözüm için ilgili soruya bakın:

Sayı girişi kaydırma için HTML5 olay dinleyicisi - yalnızca Chrome


2
Teşekkürler Seymon, bunu jQuery ile tüm sayı girişleri için şu şekilde yapmayı başardım: $(':input[type=number]' ).live('mousewheel',function(e){ $(this).blur(); });Varsayılanı önlemek yerine bulanıklık kullandım, böylece sayfanın kaymasını engellemiyor!
Thibaut Colson

Bulanıklaştırma konusunda güzel bir ek, yine de sayfa kaydırmaya izin verebileceğinizi bilmiyordum. Cevabımı güncelledim.
Simon Perepelitsa

13
FYI, live()kullanımdan kaldırıldı. Şimdi şunları kullanmalısınız on(): $(':input[type=number]').on('mousewheel',function(e){ $(this).blur(); });
Saeid Zebardast

3
@SaeidZebardast Yorumunuz bir cevap olmayı hak ediyor
snumpy

Modern tarayıcı için lütfen wheelyerine event kullanın mousewheel. Referans: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

16

Basitçe HTML onwheel özelliğini kullanabilirsiniz.

Bu seçeneğin, sayfanın diğer öğeleri üzerinde gezinmeye etkisi yoktur.

Ve tüm girdiler için bir dinleyici eklemek, dinamik olarak posterior olarak oluşturulan girdilerde çalışmaz.

Ek olarak, giriş oklarını CSS ile kaldırabilirsiniz.

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
Sağ ol, kanka!! Angular - Material 6
Nasiruddin Saiyed


Bu CSS'yi birçok kaynakta bulabiliriz. Her neyse, CSS yalnızca bir bonus. Sorunun gerçek çözümü HTML onwheel özelliğidir. ;-)
Maikon Matheus

5
Bu çözümü beğendim! Teşekkürler. Benim durumumda onBlur()beklendiği gibi değildi. return falseGerçekten "tekerlek üzerinde hiçbir şey yapmamak" yerine basit bir şey kurdum . <input type="number" onwheel="return false;">
Daniel

14

@Semyon Perepelitsa

Bunun için daha iyi bir çözüm var. Bulanıklaştırma , odağı girdiden kaldırır ve bu, istemediğiniz bir yan etkidir. Bunun yerine evt.preventDefault'u kullanmalısınız. Bu, kullanıcı kaydırdığında girişin varsayılan davranışını engeller. İşte kod:

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

6
Çalışır, ancak olay balon olmaz, bu nedenle sayfa kaymaz. Varsayılan davranışı (sayfa kaydırma) bulanıklaştırmadan korumanın bir yolu var mı?
GuiGS

Modern tarayıcı için lütfen wheelyerine event kullanın mousewheel. Referans: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

7

Öncelikle fare tekerleği olayını aşağıdakilerden biriyle durdurmalısınız:

  1. İle devre dışı bırakılıyor mousewheel.disableScroll
  2. İle kesişmek e.preventDefault();
  3. Odağı öğeden kaldırarak el.blur();

İlk iki yaklaşım hem pencerenin kaydırılmasını durdurur hem de sonuncusu odağı öğeden kaldırır; her ikisi de istenmeyen sonuçlardır.

Bir geçici çözüm, el.blur()öğeyi bir gecikmeden sonra kullanmak ve yeniden odaklamaktır:

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

3
İyi görünen bir çözüm, ancak test ederken bu çözümün odak çalmak gibi bir yan etkisi olduğunu buldum. Bunu var hadFocus = el.is(':focus');yapmak için ince ayar yaptım : öğenin odak olup olmadığını görmek için bir test: bulanıklaştırmadan önce ve sonra yalnızca hadFocs doğruysa zaman aşımını ayarlayacak bir koruma.
Rob Dawson

3

React ile çalışan ve çözüm arayan herkes için. En kolay yolun onWheelCapture prop'u Input bileşeninde şu şekilde kullanmak olduğunu öğrendim:

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


2

Sağlanan yanıtlar Firefox'ta (Quantum) çalışmıyor. Olay dinleyicisinin fare tekerleğinden tekerleğe değiştirilmesi gerekiyor:

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

Bu kod, Firefox Quantum ve Chrome'da çalışır.


2

Typescript Varyasyonu

Typecript, tür güvenliği için HTMLElement ile çalıştığınızı bilmesi gerekir, aksi takdirde birçok Property 'type' does not exist on type 'Element'türde hata görürsünüz .

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

1

Kendim için çözmeye çalışırken, bunun üst öğesine üzerine yeniden ateşe yakaladı olay çalışarak numara değişse devre dışı bırakırken girdi sayfanın kaydırma ve odak korumak için aslında mümkün olduğunu fark <input type="number"/>o yakalandı hangi , basitçe şöyle:

e.target.parentElement.dispatchEvent(e);

Ancak bu, tarayıcı konsolunda bir hataya neden oluyor ve kasıtlı olarak geçersiz bir kod olduğu için muhtemelen her yerde çalışacağı garanti edilmiyor (yalnızca Firefox'ta test ettim).

En azından Firefox ve Chromium'da iyi çalışan başka bir çözüm, <input>öğeyi geçici olarak şu şekilde yapmaktır readOnly:

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); });

Fark ettiğim bir yan etki, readOnlyalanlar için farklı stillere sahipseniz alanın bir anlığına titremesine neden olabileceğidir , ancak en azından benim durumum için bu bir sorun gibi görünmüyor.

Benzer şekilde, (James'in cevabında açıklandığı gibi) readOnlyözelliği değiştirmek yerine blur(), alanı ve sonra focus()geri alabilirsiniz, ancak yine, kullanımdaki stillere bağlı olarak bir miktar titreme meydana gelebilir.

Alternatif olarak, buradaki diğer yorumlarda da belirtildiği gibi, preventDefault()bunun yerine sadece etkinliği arayabilirsiniz . Yalnızca wheelodakta olan ve fare imlecinin altındaki sayı girdilerindeki olayları işlediğinizi varsayarsak (yukarıdaki üç koşul bunu belirtir), kullanıcı deneyimi üzerindeki olumsuz etki hiçbirine yakın olmayacaktır.


1

JavaScript gerektirmeyen bir çözüm istiyorsanız, bazı HTML işlevlerini bir CSS sözde öğesi ile birleştirmek işe yarar:

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>

Bu işe yarar çünkü <label>bir form alanıyla ilişkili bir içeriğin üzerine tıklamak alana odaklanacaktır. Ancak, sözde öğenin alanın üzerindeki "pencere bölmesi" fare tekerleği olaylarının ona ulaşmasını engeller.

Dezavantajı, yukarı / aşağı döndürücü düğmelerinin artık çalışmamasıdır, ancak yine de bunları çıkardığınızı söylediniz.


: Teoride, öncelikle odaklı olmak girdisine gerek kalmadan içerik menüsünü geri verebilir :hoverstilleri olmamalıdır tarayıcılar beri kaydırdığı, performans nedenleriyle kaydırma sırasında hesaplamaya kaçının zaman ateş, ama ben iyice çapraz tarayıcı / cihaz değil var test etti.


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

En kolay çözüm, onWheel={ event => event.currentTarget.blur() }}girdinin kendisini eklemektir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.