Search code examples
javascriptiphonedrag-and-dropmobile-safaritouch-event

touchEnd and onMouseUp BOTH firing from iPad


I'm building a page that will be used on laptops and iPads. So, the majority of the code (it's drag/drop heavy) is duplicated across mouse events and touch events. But now I'm finding a really strange behavior: when used on a laptop, everything is fine, but when used on an iPad, periodically the touchEnd fires mouseUp...and because the overall goal of the page is a sequence of events, this throws the whole thing off track (step 'n' was achieved, but then the mouseUp function re-tests for it, and since it's already done, that fails)

It took quite awhile to figure that out (since I didn't think it was possible) but by putting unique log message in the different versions, I can see that in my logs on the iPad, I get a 'mouse mistake' message.

Because this cross event behavior isn't logical to me I'm not sure how to continue debugging, so would appreciate whatever advice anyone can give. Here are the primary pieces of code, followed by a sample log FROM THE IPAD. Thanks again.

function touchEnd(event)
{
    console.log('touchEnd fired\n');
    if (_dragElement != null)
    {
        if((ExtractNumber(_dragElement.style.left)<-30)&&(ExtractNumber(_dragElement.style.top)<200)&&(event.touches.length==0)){   
            console.log(_dragElement.id+' in hand\n');
            if(process[correct].indexOf(_dragElement.id)>=0){
                console.log('--CORRECT--\n');
                hide(_dragElement.id);
                //hide('hand');
                correct++;
                document.getElementById('speech').innerHTML=phrases[correct];
                _dragElement = null;
                return false;
            }
            else{
                console.log('--WRONG--\n');
                document.getElementById(_dragElement.id).style.top = document.getElementById(_dragElement.id).defaultTop+'px';
                document.getElementById(_dragElement.id).style.left = document.getElementById(_dragElement.id).defaultLeft+'px';
                mistakeCounter++;
                if(mistakeCounter==10){
                    console.log('ejection\n');
                    ejection();
                }
                else if(mistakeCounter==9){
                    document.getElementById('speech').innerHTML='If you do that again I\'ll have to ask you to leave';
                    console.log('warning text\n');
                }
                else if(mistakeCounter<9&&mistakeCounter>5){
                    document.getElementById('speech').innerHTML=bigMistakes[Math.floor(Math.random()*bigMistakes.length)];
                    console.log('big mistake text\n');
                }
                else{
                    document.getElementById('speech').innerHTML=mistakes[Math.floor(Math.random()*mistakes.length)];
                    console.log('mistake text\n');
                }
                _dragElement = null;
            }
        }
    }
    //interactions();
}

function OnMouseUp(e)
{
    if (_dragElement != null)
    {
        _dragElement.style.zIndex = _oldZIndex;
        document.onmousemove = null;
        document.onselectstart = null;
        _dragElement.ondragstart = null;
        _dragElement = null;

        for(i=0;i<tools.length;i++){
            if((ExtractNumber(document.getElementById(tools[i].id).style.left)<-30)&&(ExtractNumber(document.getElementById(tools[i].id).style.top)<200)&&(ExtractNumber(document.getElementById(tools[i].id).style.top)>-800)&&(ExtractNumber(document.getElementById(tools[i].id).style.left)>-800)){

                if(process[correct].indexOf(tools[i].id)>=0){
                    hide(tools[i].id);
                    //hide('hand');
                    correct++;
                    document.getElementById('speech').innerHTML=phrases[correct];

                }
                else{
                    document.getElementById(tools[i].id).style.top = document.getElementById(tools[i].id).defaultTop+'px';
                    document.getElementById(tools[i].id).style.left = document.getElementById(tools[i].id).defaultLeft+'px';
                    mistakeCounter++;
                    if(mistakeCounter==10){
                        console.log('mouse ejection\n');
                        ejection();
                    }
                    else if(mistakeCounter==9){
                        console.log('mouse warning text\n');
                        document.getElementById('speech').innerHTML='If you do that again I\'ll have to ask you to leave';
                    }
                    else if(9>mistakeCounter&&mistakeCounter>5){
                        console.log('mouse big mistake text\n');
                        document.getElementById('speech').innerHTML=bigMistakes[Math.floor(Math.random()*bigMistakes.length)];
                    }
                    else{
                        console.log('mouse mistake text\n');
                        document.getElementById('speech').innerHTML=mistakes[Math.floor(Math.random()*mistakes.length)];
                    }

                }
            }

        }

    }
    //check positions
    //interactions();
}

log:

touchEnd fired
safetyAwl in hand
--CORRECT--
touchEnd fired
curvedProbe in hand
--CORRECT--
touchEnd fired
tap55 in hand
--CORRECT--
mouse mistake text

Solution

  • I 'solved' this by changing the first OnMouseUp if statement to test whether it was an iOS device:

    if ((_dragElement != null)&&(!navigator.userAgent.match('iPad'))&&(!navigator.userAgent.match('iPhone'‌​)))

    and while that works, it still seems strange to me that it tries to fire so I'm skeptical that is the BEST answer