IScroll 4 no funciona con el elemento form <select> iPhone Safari y navegador Android

Estoy usando este código 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> no funciona en iPhone y Android. Cuando toco la caja de selección, no pasa nada.

Estoy usando iScroll 4 que está creando el problema.

 <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> 

Creo que esta es una solución, pero no sé cómo implementarla.

El problema es que iScroll cancela el comportamiento predeterminado de su etiqueta de select (No es una implementación muy buena si me pregunta).

Esto ocurre en la función _start() en la línea 195:

 e.preventDefault(); 

Si comenta eso, notará que la etiqueta de select funciona de nuevo.

Pero comentarlo significa que has hackeado la biblioteca, lo que podría romper la funcionalidad deseada de iScroll. Así que aquí hay una solución mejor:

 var selectField = document.getElementById('Field10'); selectField.addEventListener('touchstart' /*'mousedown'*/, function(e) { e.stopPropagation(); }, false); 

Ese código permitirá que el comportamiento predeterminado ocurra, sin propagar el evento a iScroll donde atornilla todo.

Puesto que su JS no está dentro de ningún evento jQuery-like onReady() , tendrá que asegurarse de poner este código DESPUÉS del HTML donde se definen los elementos select .

Tenga en cuenta que para los dispositivos móviles el evento es touchstart , pero para el navegador de su PC se realizará

Tuve el mismo problema en el iScroll 4.1.9 en Android, acabo de reemplazar la línea 95 (en mi versión):

 onBeforeScrollStart: function (e) { e.preventDefault(); }, 

Por:

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

Que permiten enfocar las etiquetas de entrada, seleccionar y textarea

Finalmente arregló esto para Android. Terminó modificando un par de líneas en iscroll.js

Así es como inicializamos 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(); } }); 

El onBeforeScrollStart es lo que permite que los comportamientos predeterminados de los controles tengan lugar. El navegador de Android parece tener problemas con useTransform, así que a su vez a false.

Finalmente, es necesario excluir algún código de iscroll adicional cuando useTransform es falso:

 // 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; 

Probado varios otros métodos antes de darse cuenta de que tenía que ver con el css que iscroll añade.

Aquí está la solución

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

Otro ejemplo de código para la solución. Y gracias por comentarios anteriores! Uso de JQuery!

Después:

 $(document).ready(function() { document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); document.addEventListener('DOMContentLoaded', setTimeout(function () { loaded(); }, 200), false); }); 

En la función cargada

 function loaded() { var allSelects = $('select'); allSelects.each(function(index, item) { item.addEventListener('touchstart' /*'mousedown'*/, function(e) { e.stopPropagation(); }, false); }); } 

Sustitución de la línea, onBeforeScrollStart: function (e) { e.preventDefault(); }, onBeforeScrollStart: function (e) { e.preventDefault(); },

Por

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

En iScroll.js Obras

Comience con este código. Esta solución funcionó para mí:

 <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> 

Sé que estoy tarde, pero podría ser útil para alguien,

Escriba el código siguiente en el evento de show de páginas, pero asegúrese de que los identificadores de div no sean los mismos.

Es porque, iscroller evita los comportamientos predeterminados de los elementos

  $('#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); }); 

Llego tarde, pero te dejo mi solución.

Si estás usando jQuery puedes intentarlo.

 $('input, textarea, button, a, select').off('touchstart mousedown').on('touchstart mousedown', function(e) { e.stopPropagation(); }); 
  // 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 }); 

Para mí, sólo necesito añadir click: true en la última línea … Pasé todo el día depurando e implementando todas las soluciones sugeridas sin éxito …

Él cualquiera.

Sé que sobre todas sus respuestas pero tengo nueva manera de ofrecer. Sin java-script o drop iscroll funciones.

Los grandes problemas con toda esta solución es cuando se desplaza en el elemento de entrada no tiene desplazamiento en la página. Cuando usted hace apenas una o dos entrada no es realmente materia pero cuando la página es una forma usted tiene gran problema para desplazar la página.

La solución i que ofrece es envolver la entrada en la etiqueta etiqueta o hacer la etiqueta de la etiqueta con el puntero a la entrada. Luego hacer con posicionamiento absoluto y z-index la etiqueta por encima de la entrada. Cuando toque la etiqueta se enfoca la entrada.

Y ejemplo por favor

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

También puede de esta manera poner el lado de la etiqueta de la entrada y con la posición absoluta de la entrada poner eso en el área de la etiqueta

Está trabajando en 100%, compruébelo

Hay un error con Android cuando -webkit-transform: translate3d se aplica a un contenedor que tiene un cuadro de selección o una contraseña [1]. El área en caja para activar esos elementos se mueve, y no están donde crees que estarían. Además, los cuadros de contraseña pintan en una ubicación diferente, por lo que parece que tiene dos elementos de entrada en lugar de uno.

Trabajo en AppMobi y hemos desarrollado una biblioteca de herramientas que tiene arreglos para estos. Hemos implementado widgets personalizados de cuadro de selección y un reemplazo para el campo de entrada de contraseña. Compruébelo abajo.

https://github.com/imaffett/AppMobi.toolkit

[1] Creo que el autor del comentario está hablando de este error https://bugs.webkit.org/show_bug.cgi?id=50552

Estoy un poco tarde para el juego, pero si alguien sigue interesado, tomé el enfoque de @bastien y lo retocó un poco para que funcione en Android. Estoy usando JQM con mi implementación.

Básicamente lo que hice fue:

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

Básicamente, todo lo que necesitas hacer es destruir tu instancia de iScroll cuando el usuario selecciona un elemento de formulario, pero antes de que realice el desplazamiento (onBeforeScrollStart) y si el usuario hace clic en cualquier elemento dentro del elemento con el atributo personalizado data-iscroll="scroller" , pueden desplazarse usando iScroll como de costumbre.

 <div data-role="page" id="pageNameHere" data-iscroll="enable"> 

Aquí hay una solución muy fácil que funcionó para mí. Me di cuenta en los navegadores de Android que en la carga inicial de la página no podía hacer clic en un cuadro de selección, pero pude hacer clic en un campo de entrada de texto que estaba utilizando para la búsqueda. Entonces me di cuenta de que después de hacer clic en el campo de entrada de texto, me reconocería haciendo clic en una caja de selección. Así que todo lo que hice fue añadir esto a la función de JavaScript que estaba usando para cargar la página de búsqueda …

 $('#search').focus(); 

Así que cuando la página de búsqueda se carga, se centra automáticamente en el campo de entrada de texto, pero no aparece el teclado, que es exactamente lo que quería. Lo siento mi ejemplo no es de acceso público, pero espero que esto todavía puede ayudar a alguien.

Pruebe esta solución si (e.target.nodeName.toLowerCase () == "seleccione" || e.target.tagName.toLowerCase () == 'input' || e.target.tagName.toLowerCase () == 'textarea ') {
regreso; }

¿Qué pasa, que funciona para mí !:

 $('input, select').on('touchstart', function(e) { e.stopPropagation(); }); 

Incluso si ha excluido elementos de formulario en onBeforeScrollStart (), hay otro error en el navegador / webview de Android 2.2 / 2.3:

https://www.html5dev-software.intel.com/viewtopic.php?f=26&t=1278 https://github.com/01org/appframework/issues/104

No se pueden introducir caracteres chinos en elementos de entrada en la div con el estilo css "-webkit-transform". El iscroll 4 aplicó el "-webkit-transform" con el scroller div.

La solución es mantener los campos de formulario en una div absoluta fuera del scroller.

El error del navegador de Android es el resultado de una versión muy antigua de WebKit dentro de Android, incluso dentro de Android 4.3. La causa raíz del error – el procesamiento incorrecto del evento de clic que iScroll devuelve al navegador (la eliminación de preventDefault simplemente deja de enviar este evento de clic) El navegador Chrome de Android está libre de este error porque ha actualizado la biblioteca de WebKit dentro.

Esperando la actualización de Android WebKit de Google.

  • Buscando una alternativa para iScroll (Scrolling Div's en iOS / Webkit)
  • Cómo detectar si la aplicación web se ejecuta independientemente en Chrome Mobile
  • ¿Hay algún uso de favicon.ico para sitios web móviles?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.