2012-09-18 19 views
6

Uso preventDefault() su touchstart sul documento per impedire lo scorrimento su una pagina. Sfortunatamente questo impedisce troppo. L'utente non può più mettere a fuoco un input (e aprire la tastiera virtuale). Usando jQuery focus(), posso focalizzare l'input su un touchstart. Questo apre la tastiera virtuale su iOS (il più delle volte), ma mai su Android.Previene lo scorrimento sul browser mobile, senza impedire la messa a fuoco degli ingressi

Sfondo:

ho una pagina web che voglio fare come molto simile a un'app mobile possibile. Mi preoccupo solo di Android e iOS, ma di qualsiasi fattore di forma. Comincio rendendo il contenuto della pagina esattamente della stessa dimensione della dimensione dello schermo. Questo è bello finché l'utente non mette il dito sulla pagina. Devo impedire lo scorrimento dell'utente. Il seguente codice realizza questo, ma in modi leggermente diversi sui due sistemi operativi.

$(document).on('touchstart', function(e) { 
    e.preventDefault(); 
}); 

Su iOS, questo impedisce lo scorrimento elastico: dove un utente può rivelare una trama dietro la pagina web tentando di scorrere fuori dalla pagina. La funzione è piacevole per una normale pagina web, ma nel mio caso toglie nulla alla UX.

Su Android, impedisce la rivelazione di un trucco pratico che utilizzo per nascondere la barra degli indirizzi. I browser Android iniziano con la barra degli indirizzi visibile, ma quando l'utente scorre verso il basso della pagina, scompare. Per forzare a livello di codice il browser a nascondere la barra degli indirizzi, aggiungi semplicemente questa riga di codice alla funzione chiamata al caricamento.

$('html, body').scrollTop(1); 

Si tratta di una (ma anche l'unico) modo hacky per dire al browser di Android che abbiamo scorrere, e la barra degli indirizzi non è più necessario.

Senza il preventDefault sul documento, il browser Android consentirà lo scorrimento e la barra degli indirizzi può essere rivelata.

Quindi, entrambi i sistemi operativi hanno una buona ragione per fare in modo che preventDefault() venga chiamato su ogni touchstart del documento, ma impedisce troppo. Toccando su un campo di input non fa nulla. L'utilizzo di una chiamata a jQuery focus() può aiutare, ma apre solo la tastiera virtuale su iOS, non su Android.

$('input').on('touchstart', function() { 
    $(this).focus(); 
}); 

Come posso impedire che la pagina da scorrere, ma utilizzare le funzionalità native del browser per dare fuoco ai campi di input?

Nota: Questo codice

$(document).on('touchstart', function(e) { 
    if (e.target.nodeName !== 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

è viziata in quanto l'utente può ancora scorrere la pagina fino a quando il contatto iniziale ha origine dall'interno del campo di inserimento.

risposta

8

In realtà ho risolto questo problema su un altro progetto, l'ho dimenticato e l'ho ricordato per la maggior parte durante la digitazione.

La chiave è semplicemente farlo sul touchmove.

$(document).on('touchmove', function(e) { 
    e.preventDefault(); 
}); 

Tuttavia, preventDefault su TouchStart fa ogni genere di cose belle, come prevenire l'immagine di menu Salva su un gesto abilitato presentazione. Anche i miei progetti includono questo.

$(document).on('touchstart', function(e) { 
    if (e.target.nodeName !== 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

Se qualcuno ha qualche suggerimento su contenuti aggiuntivi o come riformattare questo in modo che possa raggiungere un pubblico maggiore che sarebbe grande. Non ho mai visto il contenuto che ho qui tutto in un posto, quindi ho sentito che doveva essere su SO.

0

Combina i due!

// prevent scrolling from outside of input field 
$(document).on('touchstart', function(e) { 
    if (e.target.nodeName !== 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

// prevent scrolling from within input field 
$(document).on('touchmove', function(e) { 
    if (e.target.nodeName == 'INPUT') { 
     e.preventDefault(); 
    } 
}); 

Questo probabilmente non è perfetto sia, e sono particolarmente preoccupato che la prima funzione impedirà seguendo i link, ma lascio ad altri di fare test approfonditi.

0

La semplice risposta alla tua domanda è non utilizzare "preventDefault" invece di utilizzare la proprietà css di pointer-events per disabilitare lo scorrimento sull'elemento che scorre.

CSS per gli ingressi:

input { 
    pointer-events: auto !important; 
} 

TouchStart listener di eventi:

document.body.addEventListener('touchstart', function(e) { 
    if (e.target.nodeName === 'INPUT') { 
     this.style.pointerEvents = 'none'; 
    } 
}); 

Sarà necessario reimpostare il puntatore-eventi quando si sfocare l'ingresso.

document.body.pointerEvents = 'auto'; 

+1 Buona domanda

+0

Quindi si modifica il DOM su ogni TouchStart e su ogni touchend. Forse questo non è il modo leggero, se consideriamo le prestazioni. –

Problemi correlati