J'utilise ce code HTML:
<form action="#" method="post">
<fieldset>
<label class="desc" id="title10" for="Field10">
How many children do you have?
</label>
<select id="Field10" name="Field10" class="field select large" tabindex="5">
<option value="0" selected="selected">0 </option>
<option value="1">1 </option>
<option value="2">2 </option>
<option value="3">3 </option>
<option value="4">4 </option>
<option value="5">5 </option>
<option value="6">6 </option>
<option value="7">7 </option>
<option value="8">8 </option>
<option value="9">9 </option>
</select>
<input type="submit" value="Send message" />
</fieldset>
</form>
<select>
ne fonctionne pas sur iPhone et Android. Lorsque je tape sur la zone de sélection, rien ne se passe.
J'utilise iScroll 4 qui crée le problème.
<script type="application/javascript" src="iscroll-lite.js"></script>
<script type="text/javascript">
var myScroll;
function loaded() {
myScroll = new iScroll('wrapper');
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', loaded, false);
</script>
Je pense ceci est une solution mais je ne sais pas comment la mettre en œuvre.
Le problème est qu'iScroll annule le comportement par défaut de votre balise select
(ce n'est pas une très bonne implémentation si vous me le demandez).
Cela se produit dans la fonction _start()
à la ligne 195:
e.preventDefault();
Si vous le commentez, vous remarquerez que la balise select
fonctionne à nouveau.
Mais commenter cela signifie que vous avez piraté la bibliothèque, ce qui pourrait casser d'autres fonctionnalités souhaitables d'iScroll. Alors voici une meilleure solution de contournement:
var selectField = document.getElementById('Field10');
selectField.addEventListener('touchstart' /*'mousedown'*/, function(e) {
e.stopPropagation();
}, false);
Ce code permettra au comportement par défaut de se produire, sans propager l'événement à iScroll où il visse tout.
Étant donné que votre JS ne fait partie d'aucun événement onReady()
de type jQuery, vous devez vous assurer de bien mettre ce codeAPR&EGRAVE;Sle code HTML où vos éléments select
sont définis.
Notez que pour les appareils mobiles l'événement est touchstart
, mais pour le navigateur de votre PC, il sera mousedown
J'ai eu le même problème sur l'iScroll 4.1.9 sur Android, je viens de remplacer la ligne 95 (sur ma version):
onBeforeScrollStart: function (e) { e.preventDefault(); },
par :
onBeforeScrollStart: function (e) {var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase():(e.target ? e.target.nodeName.toLowerCase():''); if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') e.preventDefault(); },
qui permettent de se concentrer sur les balises input, select et textarea
Enfin résolu cela pour Android. Nous avons fini par modifier quelques lignes dans iscroll.js
Voici comment initialiser iScroll.
// code from https://github.com/cubiq/iscroll/blob/master/examples/form-fields/index.html
// don't preventDefault for form controls
_menuScroll = new iScroll('menu_wrapper',{
useTransform: false,
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1) target = target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA')
e.preventDefault();
}
});
Le onBeforeScrollStart est ce qui permet aux comportements par défaut des contrôles d'avoir lieu. Le navigateur Android semble avoir un problème avec useTransform, donc passez à false.
Enfin, certains codes iscroll supplémentaires devaient être exclus lorsque useTransform est false:
// iscroll.js v4.1.9
// line 216:
if (that.options.useTransform) bar.style.cssText += ';pointer-events:none;-' + vendor + '-transition-property:-' + vendor + '-transform;-' + vendor + '-transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);-' + vendor + '-transition-duration:0;-' + vendor + '-transform:' + trnOpen + '0,0' + trnClose;
// line 295:
if (that.options.useTransform) that[dir + 'ScrollbarIndicator'].style[vendor + 'Transform'] = trnOpen + (dir == 'h' ? pos + 'px,0' : '0,' + pos + 'px') + trnClose;
J'ai essayé plusieurs autres méthodes avant de me rendre compte que cela avait à voir avec les CSS que iscroll ajoute.
Je sais que je suis en retard, mais cela pourrait être utile pour quelqu'un,
écrivez le code suivant dans l'événement pageshow, mais assurez-vous que les identifiants div ne sont pas identiques.
c'est parce que, iscroller empêche les comportements par défaut des éléments
$('#yourpage').bind('pageshow',function (event, ui) {
var myScroll;
if (this.id in myScroll) {
myScroll[this.id].refresh();
}else{
myScroll[this.id] = new iScroll('wrapper', { //wrapper is div id
checkDOMChanges: true,
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1)
target =target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA'){ e.preventDefault(); }
}
});
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
});
Voici la solution
/* on page add this after all scripts */
<script type="text/javascript">
var myScroll;
function loaded() {
myScroll = new iScroll('wrapper');
}
document.addEventListener('DOMContentLoaded', function(){ setTimeout(loaded,500);}, false);
</script>
/* attach a script for fix */
$(document).ready(function(){
var my_select = document.getElementsByTagName('select');
for (var i=0; i<my_select.length; i++) {
my_select[i].addEventListener('touchstart' /*'mousedown'*/, function(e) {
myScroll.destroy();
setTimeout(function(){myScroll = new iScroll('wrapper');},500);
}, false);
}
/*if you have input problems */
var input = document.getElementById('input');
if (input) {
input.addEventListener('touchstart' /*'mousedown'*/, function(e) {
e.stopPropagation();
}, false);
}
});
Commencez avec ce code. Cette solution a fonctionné pour moi:
<script type="text/javascript">
var myScroll;
function iScrollLoad() {
myScroll = new iScroll('wrapper');
enableFormsInIscroll();
}
function enableFormsInIscroll(){
[].slice.call(document.querySelectorAll('input, select, button, textarea')).forEach(function(el){
el.addEventListener(('ontouchstart' in window)?'touchstart':'mousedown', function(e){
e.stopPropagation();
})
})
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', function () { setTimeout(iScrollLoad, 200); }, false);
</script>
Remplacement de la ligne, onBeforeScrollStart: function (e) { e.preventDefault(); },
Par
onBeforeScrollStart: function (e) {
var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase():(e.target ? e.target.nodeName.toLowerCase():'');
if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') {
e.preventDefault();
}
},
Dans iScroll.js
Works
un autre exemple de code pour solution. et merci pour les commentaires précédents! Using Jquery!
Après:
$(document).ready(function() {
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', setTimeout(function () { loaded(); }, 200), false);
});
en fonction chargée
function loaded() {
var allSelects = $('select');
allSelects.each(function(index, item) {
item.addEventListener('touchstart' /*'mousedown'*/, function(e) { e.stopPropagation(); }, false);
});
}
Je suis en retard mais je vous laisse ma solution.
Si vous utilisez jQuery, vous pouvez essayer cela.
$('input, textarea, button, a, select').off('touchstart mousedown').on('touchstart mousedown', function(e) {
e.stopPropagation();
});
il n'importe qui.
je sais que toutes vos réponses sont correctes mais j'ai une nouvelle façon de vous offrir. sans script Java ni fonctions drop iscroll.
le gros problème de toute cette solution est que lorsque vous faites défiler l'élément de l'entrée, vous ne pouvez pas faire défiler la page. quand vous faites juste une ou deux entrées, ça n'a pas vraiment d'importance, mais quand la page est un formulaire, vous avez un gros problème pour faire défiler la page.
la solution que je propose consiste à envelopper l’entrée dans une étiquette ou à créer l’étiquette avec un pointeur sur l’entrée. faites ensuite avec positionnement absolu et z-index l’étiquette au-dessus de l’entrée. lorsque vous touchez l’étiquette, vous focalisez l’entrée.
et exemple s'il vous plaît
HTML
<fieldset>
<label>
<input type="text" />
</label>
</fieldset>
CSS
fieldset {position:relative;z-index:20;}
label {position:relative;z-index:initial;}
input {position:relative;z-index:-1;}
vous pouvez également de cette manière mettre le côté étiquette de l'entrée et avec la position absolue de l'entrée, placer cela dans la zone d'étiquette
travaille à 100%, vérifiez
// Setup myScroll
myScroll = new IScroll('#wrapper', {
scrollX: horizontalSwipe,
scrollY: !horizontalSwipe,
momentum: false,
snap: document.querySelectorAll('#scroller .slide'),
snapSpeed: 400,
bounceEasing: 'back',
keyBindings: true,
click: true
});
Pour moi, il me suffit d’ajouter un clic: true sur la dernière ligne ... J'ai passé toute la journée à déboguer et à mettre en œuvre toutes les solutions suggérées sans succès ...
Même si vous avez exclu des éléments de formulaire dans onBeforeScrollStart (), il existe un autre bogue dans le navigateur/affichage Web Android 2.2/2.3:
https://www.html5dev-software.intel.com/viewtopic.php?f=26&t=1278https://github.com/01/appframework/issues/104
Vous ne pouvez pas saisir de caractères chinois dans les éléments d’entrée du div avec un style CSS "-webkit-transform". L'iscroll 4 a appliqué le "-webkit-transform" au scroller div.
La solution consiste à conserver les champs de formulaire dans un div absolu en dehors du scroller.
Le bogue du navigateur Android est le résultat d'une très ancienne version de WebKit dans Android, même dans Android 4.3. La cause première du bogue - le traitement incorrect de l'événement de clic envoyé par iScroll au navigateur (la suppression de preventDefault cesse simplement d'envoyer cet événement de clic) Le navigateur Android Chrome est exempt de ce bogue car il a mis à niveau la bibliothèque WebKit.
En attente de la mise à niveau Android WebKit de Google.
essayez cette solution if (e.target.nodeName.toLowerCase () == "select" || e.target.tagName.toLowerCase () == 'input' || e.target.tagName.toLowerCase () == 'textarea') __. {
revenir; }
Voici une solution très facile qui a fonctionné pour moi. J'ai remarqué dans les navigateurs Android que, lors du chargement initial de la page, je ne pouvais pas cliquer sur une zone de sélection, mais que je pouvais cliquer sur un champ de saisie de texte que j'utilisais pour la recherche. Ensuite, j'ai remarqué qu'après avoir cliqué sur le champ de saisie de texte, il me reconnaît en cliquant sur une zone de sélection. Donc tout ce que j'ai fait a été d'ajouter ceci à la fonction javascript que j'utilisais pour charger la page de recherche ...
$('#search').focus();
Ainsi, lorsque la page de recherche est chargée, elle se concentre automatiquement sur le champ de saisie de texte mais ne fait pas apparaître le clavier, ce qui est exactement ce que je voulais. Désolé, mon exemple n'est pas accessible au public, mais j'espère que cela pourra toujours aider quelqu'un.
Vérifie ça. Cela a résolu mon problème
https://github.com/cubiq/iscroll/issues/576
En option j'ai sélectionné
click:false, preventDefaultException:{tagName:/.*/}
Je suis un peu en retard pour le jeu, mais si quelqu'un est toujours intéressé, j'ai pris l'approche de @ bastien et l'ai légèrement modifié pour qu'il fonctionne sur Android. J'utilise JQM avec mon implémentation.
En gros, ce que j'ai fait était:
function scrollMe(element) {
var contentID = $wrapper.get(0).id;
var scroller = Elm.find('[data-iscroll="scroller"]').get(0);
if (scroller) {
var iscroll = new iScroll(contentID, {
hScroll : false,
vScroll : true,
hScrollbar : false,
vScrollbar : true,
fixedScrollbar : true,
fadeScrollbar : false,
hideScrollbar : false,
bounce : true,
momentum : true,
lockDirection : true,
useTransition : true,
//the preceding options and their values do not have any to do with the fix
//THE FIX:
onBeforeScrollStart: function(e) {
var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase() : (e.target ? e.target.nodeName.toLowerCase():''); //get element node type
if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') e.preventDefault(); //be have normally if clicked element is not a select, option, input, or textarea.
else if (iscroll != null) { //makes sure there is an instance to destory
iscroll.destroy();
iscroll = null;
//when the user clicks on a form element, my previously instanced iscroll element is destroyed
}
},
onScrollStart: function(e) {
if (iscroll == null) { //check to see if iscroll instance was previously destoryed
var Elm = $.mobile.activePage; //gets current active page
var scrollIt = setTimeout( function(){ scrollMe(Elm) }, 0 );
} //recursively call function that re-instances iscroll element, as long as the user doesn't click on a form element
}
});
Elm.data("iscroll-plugin", iscroll);
}
}
En gros, tout ce que vous avez à faire est de détruire votre instance iScroll lorsqu'un élément de formulaire est sélectionné par l'utilisateur, mais avant de commencer le défilement (onBeforeScrollStart) et si l'utilisateur clique sur un élément de l'élément avec l'attribut personnalisé data-iscroll="scroller"
, il en utilisant iScroll comme d'habitude.
<div data-role="page" id="pageNameHere" data-iscroll="enable">
Il existe un bogue avec Android lorsque -webkit-transform: translate3d est appliqué à un conteneur contenant une zone de sélection ou un champ de mot de passe [1]. La zone encadrée pour activer ces éléments bouge et ne correspond pas à ce que vous pensez. En outre, les zones de mot de passe Paint se trouvent à un emplacement différent, de sorte qu'il apparaît que vous avez deux éléments d'entrée au lieu d'un.
Je travaille chez AppMobi et nous avons développé une bibliothèque de boîtes à outils qui contient des correctifs pour ces problèmes. Nous avons mis en place des widgets de sélection personnalisés et un remplacement du champ de saisie du mot de passe. Vérifiez ci-dessous.
https://github.com/imaffett/AppMobi.toolkit
[1] Je pense que l'auteur du commentaire parle de ce bogue https://bugs.webkit.org/show_bug.cgi?id=50552
Ça marche pour moi !:
$('input, select').on('touchstart', function(e) {
e.stopPropagation();
});