web-dev-qa-db-ja.com

iScroll 4がフォーム<select>要素のiPhone SafariおよびAndroid browserで機能しない

私はこの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では動作しません。 selectboxをタップしても何も起こりません。

問題を引き起こしている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>

私は これは解決策です だと思いますが、それを実装する方法がわかりません。

26
Jitendra Vyas

問題は、iScrollがselectタグのデフォルトの動作をキャンセルすることです(私に尋ねても、あまり良い実装ではありません)。

これは、195行目の_start()関数で発生します。

_e.preventDefault();
_

コメントアウトすると、selectタグが再び機能することに気付くでしょう。

しかし、コメントアウトすると、ライブラリがハッキングされて、他の望ましいiScroll機能が壊れる可能性があります。だからここに良い回避策があります:

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

このコードにより、イベントをiScrollに伝達せずにデフォルトの動作が発生し、すべてが台無しになります。

JSはjQueryのようなonReady()イベント内にないため、このコードを必ず挿入する必要があります[〜#〜] after [〜#〜] the select要素が定義されているHTML。

モバイルデバイスの場合、イベントはtouchstartですが、PCブラウザーの場合はmousedownになります

46
sym3tri

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

入力、選択、テキストエリアタグに焦点を当てることができます

10
bastien

最後に、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にしてください。

最後に、useTransformが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;

Iscrollが追加するcssと関係があることに気づく前に、他のいくつかの方法を試してみました。

6
deCastongrene

私は遅れていることを知っていますが、誰かに役立つかもしれません、

pageshowイベントに次のコードを記述しますが、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);

     });
4
Mallikarjun

これが解決策です

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

このコードから始めます。この解決策は私にとってうまくいきました:

<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
Joe L.

行の置き換え、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
Sunil P

ソリューションの別のコード例。以前のコメントに感謝します! 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);
                    });
}
2
tapin13

私は遅れましたが、私はあなたに私の解決策を残します。

JQueryを使用している場合は、それを試すことができます。

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

彼は誰でも。

私はあなたのすべての答えについて知っていますが、私は提供する新しい方法を持っています。 Javaスクリプトまたはドロップiscroll関数なし。

このすべてのソリューションの大きな問題は、入力の要素をスクロールすると、ページがスクロールされないことです。 1つまたは2つの入力を行う場合は問題ではありませんが、ページがフォームの場合、ページをスクロールするのに大きな問題があります。

私が提供するソリューションは、入力をラベルタグでラップするか、入力へのポインターでラベルタグを作成することです。次に、絶対配置を使用して、入力の上にラベルを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
g.e.manor
  // 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
  });

私にとっては、最後の行にクリック:trueを追加するだけです...一日中デバッグして、提案されたすべてのソリューションを実装して無駄にしています...

1
Zennichimaro

OnBeforeScrollStart()でフォーム要素を除外した場合でも、Android 2.2/2.3 browser/webview:に別のバグがあります:

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

「-webkit-transform」CSSスタイルのdivの入力要素に漢字を入力することはできません。 iscroll 4はスクローラーdivで「-webkit-transform」を適用しました。

解決策は、フォームフィールドをスクローラーの絶対div内に保持することです。

0
diyism

Androidブラウザーのバグは、Android内の非常に古いバージョンのWebKitの結果であり、Android 4.3。 Android Chromeブラウザは内部でWebKitライブラリをアップグレードしたため、このバグから解放されます。

Android GoogleからのWebKitアップグレードを待機しています。

0
Anatoliy Shuba

(e.target.nodeName.toLowerCase()== "select" || e.target.tagName.toLowerCase()== 'input' || e.target.tagName.toLowerCase()== 'textarea '){
戻る; }

0
Sukesh Marla

ここに私のために働いた本当に簡単な修正があります。 Androidブラウザでは、最初のページの読み込み時に選択ボックスをクリックできなかったが、検索に使用しているテキスト入力フィールドをクリックできたことがわかりました。その後、テキスト入力フィールドをクリックした後、選択ボックスをクリックしたことが認識されるので、検索ページの読み込みに使用しているJavaScript関数にこれを追加するだけでした...

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

そのため、検索ページが読み込まれると、テキスト入力フィールドに自動的にフォーカスしますが、キーボードはポップアップしません。これはまさに私が望んでいたことです。申し訳ありませんが、私の例は公開されていませんが、うまくいけば、これはまだ誰かを助けることができます。

0
Pete

これをチェックして。これで問題が解決しました

https://github.com/cubiq/iscroll/issues/576

オプションで選択しました

click:false, preventDefaultException:{tagName:/.*/}
0
A Paul

私は少しゲームに遅れましたが、誰かがまだ興味がある場合は、@ 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);
}

}

基本的には、ユーザーがフォーム要素を選択したとき、実際にスクロールを開始する前(onBeforeScrollStart)、およびユーザーが要素内のカスタム属性data-iscroll="scroller"をクリックすると、iScrollインスタンスを破棄するだけです。 、通常どおりiScrollを使用してスクロールできます。

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

Androidのバグがあり、-webkit-transform:translate3dが選択ボックスまたはパスワードボックス[1]のあるコンテナーに適用されている場合。これらの要素をアクティブにするボックス領域が移動し、さらに、パスワードボックスは別の場所にペイントするため、1つではなく2つの入力要素があるように見えます。

私はAppMobiで働いており、これらを修正したツールキットライブラリを開発しました。カスタムの選択ボックスウィジェットと、パスワード入力フィールドの置き換えを実装しました。以下をご覧ください。

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

[1]コメントの作成者がこのバグについて話していると思います https://bugs.webkit.org/show_bug.cgi?id=50552

0
user258082

それは私にとってうまくいきます!:

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