Disabilita lo scorrimento su "<input type = number>"


121

È possibile disabilitare la rotella di scorrimento modificando il numero in un campo del numero di input? Ho pasticciato con CSS specifici per il webkit per rimuovere lo spinner, ma mi piacerebbe sbarazzarmi del tutto di questo comportamento. Mi piace usare type=numberpoiché fa apparire una bella tastiera su iOS.


7
usa il tipo di input tel (type = "tel") invece di usare il tipo = numero. Apparirà una tastiera num iOS.
Praveen Vijayan

Cosa succede quando aggiungi un onscrollgestore con solo event.preventDefault()dentro?
robertc

14
A mio modesto parere, non penso nemmeno che questa dovrebbe essere una caratteristica. Se avessi voce in capitolo nello sviluppo del browser, probabilmente spingerei per rimuovere questa funzione. Non è altro che fastidioso e non conosco nessuno che lo userebbe effettivamente.
Kirkland

3
Sono totalmente d'accordo con te Kirkland. È solo una cattiva esperienza utente scorrere una pagina con un modulo e, quando un elemento di input numerico passa sotto il mouse, inizia a incrementare e la pagina smette di scorrere. Totalmente disorientante.
kjs3

3
@PraveenVijayan: Anche se questa è una soluzione alternativa, va contro qualsiasi motivo per utilizzare i nuovi tipi di input html5. In futuro è possibile che i telefoni ti diano la possibilità di scegliere il numero dai contatti o altro, il che sembrerà molto strano se intendevi che si tratta di un tipo diverso di numero.
soggezione

Risposte:


92

Impedisce il comportamento predefinito dell'evento rotellina del mouse sugli elementi del numero di input come suggerito da altri (chiamare "blur ()" normalmente non sarebbe il modo preferito per farlo, perché non sarebbe quello che vuole l'utente).

MA. Eviterei sempre di ascoltare l'evento della rotellina del mouse su tutti gli elementi del numero di input e lo farei solo quando l'elemento è a fuoco (è allora che esiste il problema). In caso contrario, l'utente non potrà scorrere la pagina quando il puntatore del mouse si trova ovunque su un elemento del numero di input.

Soluzione per 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')
})

(Delegare gli eventi di focus all'elemento del form circostante, per evitare a molti listener di eventi, che sono negativi per le prestazioni.)


2
Bella risposta. Penso che se lo facessi oggi utilizzerei Modernizr.touch per applicare in modo condizionale il listener di eventi su dispositivi non touch. Fondamentalmente ciò che user2863715 ha detto di seguito.
kjs3

Ottima risposta, ma almeno nel webkit, questo impedisce anche lo scorrimento della finestra mentre il cursore si trova sopra l'elemento di input. Pensavo che anche gli eventi della rotellina del mouse dovessero bollire.
Ryan McGeary

Quando si applica la funzione di disabilitazione scorrimento a un elemento solo quando è attivo, ciò non dovrebbe impedire lo scorrimento, quando il mouse si trova sull'elemento di input. Ma impedisce lo scorrimento della finestra, quando l'elemento è a fuoco. E sì, perché l'evento della rotellina del mouse non bolle ...: /
Grantzau

6
Questa è una bella soluzione a un comportamento che non dovrebbe esistere in primo luogo.
Jonny

Questo non funziona sulla maggior parte delle piattaforme di tipo unix gnome, osx, android (con il mouse) poiché il comportamento di scorrimento non richiede che l'input sia focalizzato. In alternativa, ho appena usato il tipo di testo degli input e ho inserito la mia restrizione numerica (perdita di scorciatoia da tastiera su / giù ma può essere aggiunta anche con js)
zeachco


21

Un ascoltatore di eventi per dominarli tutti

Questo è simile a @Simon Perepelitsa 's risposta a js puri, ma un po' più semplice, in quanto mette un ascoltatore evento l'elemento del documento e controlla se l'elemento focalizzato è immettere un numero:

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

Se vuoi disattivare il comportamento di scorrimento dei valori su alcuni campi, ma non su altri, fallo semplicemente:

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

con questo:

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

Se un input ha la classe noscroll non cambierà durante lo scroll, altrimenti tutto rimane lo stesso.

Prova qui con JSFiddle


Vedo che questo è stato downvoted. Se vedi un problema, lascia anche un commento con il voto negativo. Se mi sono perso qualcosa, vorrei sapere di cosa si tratta. Grazie.
Peter Rakmanyi

1
Per i browser moderni, utilizza event wheelinvece di mousewheel. Riferimento: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event PS. Non sono io a votare.
vee

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

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

Per l'esempio di jQuery e una soluzione cross-browser vedere la domanda correlata:

Listener di eventi HTML5 per lo scorrimento dell'input di numeri - solo Chrome


2
Grazie Seymon, sono riuscito a farlo per tutti gli input numerici con jQuery in questo modo: $(':input[type=number]' ).live('mousewheel',function(e){ $(this).blur(); });ho usato la sfocatura invece di prevenire il default così non blocca lo scorrimento della pagina!
Thibaut Colson

Bella aggiunta sulla sfocatura, non sapevo che fosse ancora possibile consentire lo scorrimento della pagina. Ho aggiornato la mia risposta.
Simon Perepelitsa

13
Cordiali saluti, live()è deprecato. Ora, dovresti usare on(): $(':input[type=number]').on('mousewheel',function(e){ $(this).blur(); });
Detto Zebardast l'

3
@SaeidZebardast Il tuo commento merita di essere una risposta
snumpy

Per i browser moderni, utilizza event wheelinvece di mousewheel. Riferimento: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

16

Puoi semplicemente usare l'HTML sulla rotella attributo .

Questa opzione non ha effetto sullo scorrimento su altri elementi della pagina.

E aggiungi un ascoltatore per tutti gli input non funzionano negli input creati dinamicamente a posteriori.

Aditionaly, puoi rimuovere le frecce di input con 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
Grazie fratello !! ha funzionato perfettamente in Angular - Material 6
Nasiruddin Saiyed il


Possiamo trovare questo CSS in molte fonti. Comunque, il CSS è solo un bonus. La vera soluzione alla domanda è l'attributo HTML onwheel. ;-)
Maikon Matheus

5
Mi piace questa soluzione! Grazie. Nel mio caso, onBlur()non era come previsto. Ho impostato un semplice return falseinvece per davvero "non fare nulla al volante". <input type="number" onwheel="return false;">
Daniel

14

@Semyon Perepelitsa

C'è una soluzione migliore per questo. La sfocatura rimuove il focus dall'input e questo è un effetto collaterale che non si desidera. Dovresti invece usare evt.preventDefault. Ciò impedisce il comportamento predefinito dell'input quando l'utente scorre. Ecco il codice:

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

6
Funziona, ma l'evento non verrà visualizzato in bolle, quindi la pagina non scorrerà. C'è un modo per mantenere il comportamento predefinito (scorrimento della pagina) senza offuscare?
GuiGS

Per i browser moderni, utilizza event wheelinvece di mousewheel. Riferimento: developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

7

Per prima cosa devi interrompere l'evento della rotellina del mouse in uno dei seguenti modi:

  1. Disabilitandolo con mousewheel.disableScroll
  2. Intercettandolo con e.preventDefault();
  3. Rimuovendo il focus dall'elemento el.blur();

I primi due approcci bloccano entrambi lo scorrimento della finestra e l'ultimo rimuove il focus dall'elemento; entrambi sono risultati indesiderabili.

Una soluzione alternativa consiste nell'utilizzare el.blur()e rimettere a fuoco l'elemento dopo un ritardo:

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

3
Una bella soluzione, ma durante i test ho scoperto che questa soluzione aveva l'effetto collaterale di rubare la concentrazione. Ho modificato questo per avere: un test per vedere se l'elemento aveva il focus: var hadFocus = el.is(':focus');prima la sfocatura, e poi una guardia per impostare il timeout solo se hadFocs era vero.
Rob Dawson

2

Le risposte fornite non funzionano in Firefox (Quantum). Il listener di eventi deve essere cambiato dalla rotellina del mouse alla rotellina:

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

Questo codice funziona su Firefox Quantum e Chrome.


2

Per chiunque lavori con React e cerchi una soluzione. Ho scoperto che il modo più semplice è usare l'elica onWheelCapture nel componente Input in questo modo:

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


2

Variazione del dattiloscritto

Il dattiloscritto deve sapere che stai lavorando con un HTMLElement per l'indipendenza dai tipi, altrimenti vedrai molti Property 'type' does not exist on type 'Element'tipi di errori.

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

1

Mentre cercavo di risolverlo da solo, ho notato che in realtà è possibile mantenere lo scorrimento della pagina e il focus dell'input disabilitando le modifiche del numero tentando di riattivare l'evento catturato sull'elemento genitore del <input type="number"/>su cui era stato catturato , semplicemente così:

e.target.parentElement.dispatchEvent(e);

Tuttavia, questo causa un errore nella console del browser e probabilmente non è garantito che funzioni ovunque (ho provato solo su Firefox), poiché si tratta di codice intenzionalmente non valido.

Un'altra soluzione che funziona bene almeno su Firefox e Chromium è quella di creare temporaneamente l' <input>elemento readOnly, in questo modo:

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

Un effetto collaterale che ho notato è che può causare uno sfarfallio del campo per una frazione di secondo se hai uno stile diverso per readOnly campi, ma almeno per il mio caso, questo non sembra essere un problema.

Allo stesso modo, (come spiegato nella risposta di James) invece di modificare la readOnlyproprietà, puoi blur()il campo e poifocus() nuovo, ma ancora una volta, a seconda degli stili in uso, potrebbe verificarsi uno sfarfallio.

In alternativa, come menzionato in altri commenti qui, puoi semplicemente chiamare preventDefault()l'evento. Supponendo che gestisci solo wheeleventi sugli input numerici che sono a fuoco e sotto il cursore del mouse (questo è ciò che significano le tre condizioni sopra), l'impatto negativo sull'esperienza utente sarebbe quasi nullo.


1

Se desideri una soluzione che non necessita di JavaScript, combinare alcune funzionalità HTML con uno pseudo-elemento CSS fa il trucco:

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>

Funziona perché facendo clic sul contenuto di un file <label> che è associato a un campo modulo si focalizzerà il campo. Tuttavia, la "finestra" dello pseudo-elemento sul campo bloccherà gli eventi della rotella del mouse dal raggiungerlo.

Lo svantaggio è che i pulsanti di selezione su / giù non funzionano più, ma hai detto di averli rimossi comunque.


In teoria, si potrebbe ripristinare il menu contestuale senza richiedere prima che l'input sia focalizzato: gli :hoverstili non dovrebbero attivarsi quando l'utente scorre, poiché i browser evitano di ricalcolarli durante lo scorrimento per motivi di prestazioni, ma non ho completamente cross-browser / dispositivo testato.


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

La soluzione più semplice è aggiungere onWheel={ event => event.currentTarget.blur() }}l'input stesso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.