7

Jquery と Jquery Mobile を使用して、Android 用の PhoneGap アプリを開発しています。

リスト内の各アイテムにバインドされた 2 つのイベントが必要なアイテムのリストがあります。「タップホールド」イベントと「クリック」イベントが必要です。私が抱えている問題は、「taphold」を実行すると、正しい「taphold」イベントが発生することです。ただし、離すとすぐにクリックイベントも発生します。タップホールド後にクリックイベントが発生しないようにするにはどうすればよいですか?

コード:

function LoadMyItems(items) {

for(var idx in items)
{
    var itemLine = '<div class="my_item" id="my_item_'+items[idx].user_item_id+'">' +
           '<img class="item_icon_32" src=./images/graphicFiles/Icon48/'+items[idx].item.graphic.graphicFiles.Icon48.filename+' />' +
           items[idx].item.name+    
           '</div>';
    $('#my_list').append('<li>'+itemLine+'</li>');
        $('#my_item_'+items[idx].user_item_id).bind('taphold', {userItem:items[idx]},ShowMyItemInfo);
        $('#my_item_'+items[idx].user_item_id).bind('click tap', {userItem:items[idx]},FitMyUpgradeItem);
        console.log('UserItem '+items[idx].user_item_id+' loaded and events bound');
    }
    $('#my_items_loader').hide();
    myScroll.refresh();
}

以下のアドバイスの後、これが私が最終的に得たものです。これは iScroll オブジェクト内で機能します。

function LoadMyItems(items) {

for(var idx in items)
{
    var itemLine = '<div class="my_item" id="my_item_'+items[idx].user_item_id+'">' +
                   '<img class="item_icon_32" src=./images/graphicFiles/Icon48/'+items[idx].item.graphic.graphicFiles.Icon48.filename+' />' +
                   items[idx].item.name+    
                   '</div>';
    $('#my_list').append('<li>'+itemLine+'</li>');

    (function(index) {
        var tapTime = 0;
        var xPos = 0;
        var yPos = 0;
        $('#my_item_'+items[index].user_item_id).bind('vmousedown vmouseup', function (event) {
            if (event.type == 'vmousedown') {

                tapTime = new Date().getTime();
                xPos = event.pageX;
                yPos = event.pageY;

                var timer = setTimeout(function() {
                    var duration = (new Date().getTime() - tapTime);
                    var xDiff = Math.abs(mouseXPos - xPos);
                    var yDiff = Math.abs(mouseYPos - yPos);
                    if(duration >= 700 && (yDiff <= 40 || mouseXPos == 0))
                        ShowItemInfo(items[index].item);
                },750);
            } else {
                //event.type == 'vmouseup'
                var duration = (new Date().getTime() - tapTime);
                var xDiff = Math.abs(event.pageX - xPos);
                var yDiff = Math.abs(event.pageY - yPos);
                tapTime = new Date().getTime();
                if (duration < 699 && yDiff <= 40) {
                    //this is a tap
                    FitMyUpgradeItem(items[index]);
                }
            }
        });

        $('#my_item_'+items[index].user_item_id).bind('touchmove',function(event) {
            event.preventDefault();
        });
    })(idx);

    console.log('UserItem '+items[idx].user_item_id+' loaded and events bound');
}
$('#my_items_loader').hide();
myScroll.refresh();
}
4

4 に答える 4

12

tapandを使用するのではなくtaphold(私が使用しようとしましたが、同じ問題が発生しました。これはイベントに固有の問題のようです) 、フラグtapholdを使用して設定し、バインドして、それがaか:かを判断できます。vmousedownvmouseuptaptaphold

var tapTime = 0;
$('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) {
    if (event.type == 'vmousedown') {
        tapTime = new Date().getTime();
    } else {
        //event.type == 'vmouseup'
        //here you can check how long the `tap` was to determine what do do

        var duration = (new Date().getTime() - tapTime);
        if (duration > 3000) {
            //this is a tap-hold
            ShowMyItemInfo(items[idx]);
        } else {
            //this is a tap
            FitMyUpgradeItem(items[idx]);
        }
    }
});

これが正しく機能するためには、ループコードの周りにIIFEを追加するか、ループのShowMyItemInfo(items[idx]);各反復を変更する変数を参照せずに機能するように変更する必要があります。IIFEを作成する簡単な方法は、を使用すること$.each()です。そうしないと、ループは次のようになります。

for(var idx in items)
{
    (function (idx) {
        ...
    })(idx);
}

IIFE=即時呼び出し関数式。これにより、IIFEに渡す変数の現在の状態の「スナップショット」を撮ることができます。したがって、渡すとidx(技術的には、2番目のインスタンスは渡される変数であり、最初のインスタンスはIIFE内で使用可能な変数であり、簡単にするために次のように変更できますids_new)、渡された値は次の場合に保存されます。tapイベントハンドラーが起動します。

アップデート

イベントtapholdを使用するのではなく、タイムアウトを設定して決定することもできます。vmouseup

//setup a timer and a flag variable
var tapTimer,
    isTapHold = false;
$('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) {
    if (event.type == 'vmousedown') {

        //set the timer to run the `taphold` function in three seconds
        //
        tapTimer = setTimeout(function () {
            isTapHold = true;
            ShowMyItemInfo(items[idx]);
        }, 3000);
    } else {
        //event.type == 'vmouseup'
        //clear the timeout if it hasn't yet occured
        clearTimeout(tapTimer);    

        //if the flag is set to false then this is a `tap` event
        if (!isTapHold) {
            //this is a tap, not a tap-hold
            FitMyUpgradeItem(items[idx]);
        }

        //reset flag
        isTapHold = false;
    }
});

このように、ユーザーが3秒間指を押した後、イベントが発生します。その場合、tapイベントハンドラーは、その3秒が発生しなかった場合にのみ起動します。

于 2012-05-08T19:20:14.653 に答える
6

イベントを定義する前に、ドキュメントの上部または任意の場所にこれを設定するだけです。

$.event.special.tap.emitTapOnTaphold = false;

次に、次のように使用できます。

$('#button').on('tap',function(){
    console.log('tap!');
}).on('taphold',function(){
    console.log('taphold!');
});
于 2014-02-18T08:59:51.057 に答える
1

個人的には、ここでの回答は問題を非常に複雑にしていると思いました。タップホールドイベントを引き続き使用し、タップホールドを離したときに発生するクリックイベントを無視できるようにする簡単な方法が必要な場合は、自分のプロジェクトでこの同じ問題をどのように解決したかを次に示します。

// We will use this flag to ignore click events we don't want
var skipNextClick = false;

//Set up your event handler.  You could do these using two handlers or one.  I chose one.

$('div.element').on('click taphold', function (e) {
    //set up a quick bool flag that is true if click
    var isClick = (e.type == 'click');

    if (isClick && !skipNextClick) {
        //run your code for normal click events here...

    }
    else if (isClick && skipNextClick) {
        //this is where skipped click events will end up...

        //we need to reset our skipNextClick flag here,
        //this way, our next click will not be ignored
        skipNextClick = false;
    }
    else {
        //taphold event

        //to ignore the click event that fires when you release your taphold,
        //we set the skipNextClick flag to true here.
        skipNextClick = true;

        //run your code for taphold events here...

    }
});
于 2015-08-10T18:47:14.747 に答える
0

代わりに、tap\vclick と taphold を使用してください。Tap イベントは、Taphold の後に 2 回発生します。

$('#my_item_'+items[idx].user_item_id).bind('vclick', ... 
$('#my_item_'+items[idx].user_item_id).bind('taphold', ...

この例では、クリックは実際にはタップホールドの後に呼び出されません..ここで確認してください: http://jsfiddle.net/YL8hj/43/

編集:

jQuery Mobile は、タッチ イベントをいくつかの要素に自動的にバインドします。iScroll を jQuery Mobile と組み合わせる場合は、別の関数を「touchmove」イベントにバインドし、イベントがバブリングしないようにすることをお勧めします ( event.preventDefault() )。これを行うと、ユーザーが iScroll 要素を操作している間、jQuery Mobile はタッチ イベントを処理できなくなります。

またhttp://appcropolis.com/blog/jquery-wrapper-for-iscroll/ クレジットhttps://stackoverflow.com/a/9408567/643500

于 2012-05-08T16:36:41.903 に答える