Подтвердить что ты не робот

IScroll 4 не работает с элементом формы <select> iPhone Safari и Android-браузер

Я использую этот код 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> не работает на iPhone и Android. Когда я нажимаю кнопку выбора, ничего не происходит.

Я использую iScroll 4, который создает проблему.

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

Я думаю, это решение, но я не знаю, как его реализовать.

4b9b3361

Ответ 1

Проблема заключается в том, что iScroll отменяет поведение вашего тега select по умолчанию (не очень хорошая реализация, если вы спросите меня).

Это происходит в функции _start() в строке 195:

e.preventDefault();

Если вы прокомментируете это, вы заметите, что тег select работает снова.

Но комментирование означает, что вы взломали библиотеку, которая может сломать другие желаемые функции iScroll. Итак, вот лучшее обходное решение:

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

Этот код позволит использовать поведение по умолчанию, не распространяя событие на iScroll, где он все закручивает.

Так как ваш JS не находится внутри какого-либо события jQuery-like onReady(), вам нужно убедиться, что вы поместите этот код ПОСЛЕ HTML, где определены ваши элементы select.

Обратите внимание, что для мобильных устройств событие touchstart, но для вашего браузера вашего компьютера это будет mousedown

Ответ 2

У меня была такая же проблема в iScroll 4.1.9 на Android, я просто заменил строку 95 (в моей версии):

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

:

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

которые позволяют сфокусироваться на тегах ввода, выбора и textarea

Ответ 3

Наконец, это исправлено для Android. Завершено изменение пары строк в iscroll.js

Здесь мы инициализируем 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();
    }
});

OnBeforeScrollStart - это то, что позволяет осуществлять поведение по умолчанию для элементов управления. У браузера Android, похоже, проблема с useTransform, поэтому поверните на false.

Наконец, некоторый дополнительный код iscroll, который необходимо исключить, когда useTransform имеет значение 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;

Пробовал несколько других методов, прежде чем понять, что это связано с css, который добавляет iscroll.

Ответ 4

Я знаю, что поздно, но это может быть полезно для кого-то,

напишите следующий код в событии showhow, но убедитесь, что div id не совпадает.

это потому, что iscroller предотвращает поведение элементов по умолчанию

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

     });

Ответ 5

Вот решение

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

Ответ 6

другой пример кода для решения. и спасибо за предыдущие комментарии! Использование JQuery!

После:

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

    document.addEventListener('DOMContentLoaded', setTimeout(function () { loaded(); }, 200), false);
});

в загруженной функции

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

Ответ 7

Замена строки, onBeforeScrollStart: function (e) { e.preventDefault(); },

По

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

В iScroll.js Работы

Ответ 8

Начните с этого кода. Это решение работало для меня:

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

Ответ 9

Я опаздываю, но я оставляю вам свое решение.

Если вы используете jQuery, вы можете попробовать это.

$('input, textarea, button, a, select').off('touchstart mousedown').on('touchstart mousedown', function(e) {
    e.stopPropagation();
});

Ответ 10

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

Для меня просто нужно добавить click: true в последней строке... Провел весь день отладки и реализации всех предлагаемых решений безрезультатно...

Ответ 11

он любой.

Я знаю обо всех ваших ответах, но у меня есть новый способ предложить. без java- script или отбрасывать функции iscroll.

большие проблемы со всем этим решением - когда вы прокручиваете элемент ввода, у вас нет прокрутки на странице. когда вы делаете только один или два входа, не имеет большого значения, но когда страница является формой, у вас есть большая проблема для прокрутки страницы.

предлагаемое решение состоит в том, чтобы обернуть ввод в тег метки или сделать тег метки для указателя на вход. затем сделайте с абсолютным позиционированием и z-index над меткой над входом. когда вы касаетесь метки, на которой вы фокусируете вход.

и пример пожалуйста

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

вы также можете таким образом поместить сторону метки на вход и с абсолютной положением входа, помещенной в область метки

работает на 100%, проверьте его

Ответ 12

Есть ошибка с Android, когда -webkit-transform: translate3d применяется к контейнеру с полем выбора или паролем [1]. Поле в коробке, чтобы активировать эти элементы, перемещается, и не там, где вы думаете, что они будут. Кроме того, поля паролей рисуются в другом месте, поэтому кажется, что у вас есть два входных элемента вместо одного.

Я работаю в AppMobi, и мы разработали библиотеку инструментальных средств, для которой есть исправления. Мы внедрили пользовательские виджеты флажков и заменили поле ввода пароля. Проверьте это ниже.

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

[1] Я думаю, автор комментария говорит об этой ошибке https://bugs.webkit.org/show_bug.cgi?id=50552

Ответ 13

Вот очень легкое решение, которое сработало для меня. Я заметил в браузерах Android, что при начальной загрузке страницы я не мог нажать на поле выбора, но мне удалось щелкнуть текстовое поле ввода, которое я использовал для поиска. Затем я заметил, что после того, как я нажал на поле ввода текста, он узнает, что я нажимаю кнопку выбора. Так что все, что я сделал, это добавить к функции javascript, которую я использовал для загрузки страницы поиска...

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

Поэтому, когда страница поиска загружается, она автоматически фокусируется на текстовом поле ввода, но не открывает клавиатуру, и именно этого я и хотел. Извините, мой пример не является общедоступным, но, надеюсь, это может помочь кому-то.

Ответ 14

Я немного опаздываю в игру, но если кто-то все еще интересуется, я применил подход @bastien и немного изменил его, чтобы заставить его работать Android. Я использую JQM с моей реализацией.

В основном, что я сделал:

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

}

В принципе, все, что вам нужно сделать, это уничтожить ваш экземпляр iScroll, когда пользователь выбирает элемент формы, но прежде чем они начнут прокрутку (onBeforeScrollStart), и если пользователь нажмет на что-либо еще внутри элемента с пользовательским атрибутом data-iscroll="scroller", они могут прокручиваться с помощью iScroll, как обычно.

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

Ответ 15

попробуйте это решение  if (e.target.nodeName.toLowerCase() == "select" || e.target.tagName.toLowerCase() == 'input' || e.target.tagName.toLowerCase() == 'textarea')           {
              вернуть;           }

Ответ 16

Как насчет того, что работает для меня!:

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

Ответ 17

Даже если вы исключили элементы формы в onBeforeScrollStart(), есть еще одна ошибка в браузере android 2.2/2.3 в браузере android:

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

Вы не можете вводить символы китайского языка в элементы ввода в div с типом css -webkit-transform. Искрол 4 применил "-webkit-transform" с помощью скроллера div.

Решение состоит в том, чтобы сохранить поля формы в абсолютном div из скроллера.

Ответ 18

Ошибка браузера Android - результат очень старой версии WebKit внутри Android, даже в Android 4.3. Коренная причина ошибки - неправильная обработка события click, которое iScroll отправляет обратно в браузер (удаление preventDefault просто прекращает отправку этого события кликов) Браузер Android Chrome свободен от этой ошибки, потому что он обновил библиотеку WebKit внутри.

Ожидание обновления Android WebKit от Google.