iScroll 4 не работает с элементом формы <select>iPhone Safari и браузером Android - PullRequest
26 голосов
/ 21 апреля 2011

Я использую этот 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>

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

Ответы [ 19 ]

46 голосов
/ 24 апреля 2011

Проблема в том, что 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-подобного onReady() события, вам нужно обязательно поместить этот код ПОСЛЕ HTML-кода, в котором определены ваши элементы select,

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

10 голосов
/ 07 октября 2011

У меня была такая же проблема на iScroll 4.1.9 на андроиде, я просто заменил строку 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(); },           

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

6 голосов
/ 20 января 2012

Наконец исправлено это для 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.

Наконец, при использовании falseTransform false следует исключить некоторый дополнительный код iscroll:

// 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 голосов
/ 10 декабря 2012

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

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

это потому, что 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);

     });
3 голосов
/ 08 июня 2011

Вот решение

/* 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);
            }    
        });
2 голосов
/ 04 декабря 2012

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

<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>
2 голосов
/ 23 апреля 2012

Замена линии, 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 Работает

2 голосов
/ 14 ноября 2011

другой пример кода для решения. и спасибо за предыдущие комментарии! Использование 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);
                    });
}
1 голос
/ 30 июня 2013

он любой.

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

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

решение, которое я предлагаю, заключается в том, чтобы обернуть ввод в тег метки илиметка тега для указателя на вход.затем сделайте с абсолютным позиционированием и 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%, отметьте

1 голос
/ 30 мая 2013
  // 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 в последнюю строку ... Потратил целый день на отладку и реализацию всех предложенных решений, но безрезультатно ...

...