2012-09-18 7 views
6

Ich benutze preventDefault() auf Touchstart auf dem Dokument, um Scrollen auf einer Seite zu verhindern. Leider verhindert dies zu viel. Der Benutzer kann den Fokus nicht mehr auf einen Eingang richten (und die Soft-Tastatur öffnen). Mit jQuery focus() kann ich den Fokus auf einen Touchstart legen. Dies öffnet die Soft-Tastatur auf iOS (die meiste Zeit), aber nie auf Android.Verhindern Scrollen in mobilen Browser, ohne die Eingabe zu verhindern Fokussierung

Hintergrund:

Ich habe eine Webseite, die ich so viel wie eine mobile app wie möglich machen will. Mir geht es nur wirklich um Android und iOS, aber um jeden Formfaktor. Ich beginne mit dem Inhalt auf der Seite genau die gleiche Größe wie die Bildschirmgröße. Das ist nett, bis der Benutzer den Finger auf die Seite legt. Ich muss das Scrollen des Benutzers verhindern. Der folgende Code erreicht dies, jedoch auf leicht unterschiedliche Weise auf den beiden Betriebssystemen.

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

Auf iOS, verhindert dies das elastische Scrollen: wo ein Benutzer eine Textur hinter der Webseite zeigen können, indem Sie versuchen, die Seite zu scrollen. Die Funktion ist gut für eine normale Webseite, aber in meinem Fall beeinträchtigt sie die UX.

Auf Android, verhindert die Enthüllung eines handlichen Hack, den ich verwende, um die Adressleiste zu verbergen. Android-Browser beginnen mit der sichtbaren Adressleiste, aber wenn der Benutzer die Seite herunterscrollt, verschwindet sie. Um den Browser programmgesteuert zu zwingen, die Adressleiste auszublenden, fügen Sie diese Codezeile einfach zu Ihrer Funktion hinzu, die beim Laden aufgerufen wird.

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

Dies ist ein Hacky (aber auch der einzige) Weg, um den Android-Browser zu sagen, dass wir geblättert haben, und die Adressleiste ist nicht mehr erforderlich.

Ohne preventDefault auf dem Dokument, erlaubt der Android-Browser Scrollen und die Adressleiste kann aufgedeckt werden.

So haben beide Betriebssysteme einen guten Grund, diese preventDefault() - Funktion bei jedem Touchstart des Dokuments aufzurufen, aber sie verhindert zu viel. Das Tippen auf ein Eingabefeld bewirkt nichts. Mit einem Aufruf von jQuery kann focus() helfen, aber öffnet nur die Soft-Tastatur auf iOS, nicht Android.

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

Wie kann ich die Seite von Scrollen, verhindern aber den Browser nativen Funktionalität nutzen für Felder Fokus Eingang zu geben?

Hinweis: Dieser Code

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

ist fehlerhaft, da der Benutzer immer noch die Seite solange die anfängliche Berührung von innerhalb des Eingabefeldes stammt bewegen kann.

Antwort

8

Ich löste dieses Problem tatsächlich bei einem anderen Projekt, vergaß es und erinnerte mich an die meiste Zeit durch das Eintippen.

Der Schlüssel ist, es nur auf touchmove zu tun.

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

jedoch prevent auf Berührungsstart tut alle Arten von netten Dingen wie das Bild speichert Menü auf einer Geste aktiviert Diashow zu verhindern. Meine Projekte beinhalten das auch.

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

Wenn jemand einige Vorschläge auf zusätzliche Inhalte hat oder wie diese zu formatieren, so dass es ein größeres Publikum zu erreichen, das wäre toll. Ich habe den Inhalt, den ich hier habe, noch nie an einem Ort gesehen, also hatte ich das Gefühl, dass es SO sein musste.

0

Kombinieren Sie die zwei!

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

Dies ist wahrscheinlich auch nicht perfekt, und ich bin besonders besorgt darüber, dass die erste Funktion Links folgen verhindern wird, aber ich werde es anderen überlassen umfangreiche Tests zu tun.

0

Die einfache Antwort auf Ihre Frage ist, verwenden Sie nicht "preventDefault" statt Zeiger-Ereignisse CSS-Eigenschaft, um das Scrollen auf dem Element, das scrollt deaktivieren.

CSS für Ihre Eingaben:

input { 
    pointer-events: auto !important; 
} 

Berührungsstart Ereignis-Listener:

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

Sie müssen die Zeiger-Ereignisse zurückgesetzt werden, wenn Sie die Eingabe verschwimmen.

document.body.pointerEvents = 'auto'; 

+1 Gute Frage

+0

So ändern Sie das DOM auf jedem Berührungsstart und auf jedem touchend. Vielleicht ist das nicht der leichte Weg, wenn wir die Aufführungen in Betracht ziehen. –

Verwandte Themen