2012-07-11 15 views
13

su mouseUp o touchEnd Voglio ottenere il riferimento dell'elemento su cui è accaduto l'evento.Come arrivare e comportarsi come mouseUp?

Demo

In questo esempio, è necessario fare clic su un elemento, trascinare il mouse e rilasciato su un altro elemento. Quando il mouse viene rilasciato, lo sfondo di quell'elemento diventa rosso. Il mio codice funziona correttamente per gli eventi del mouse, ma non sui dispositivi touch.

Quando lo touchStart si trova su un elemento e il dito viene rilasciato su un altro elemento, ricevo solo il riferimento al primo elemento.

Cosa devo modificare per rendere gli eventi di tocco funzionanti esattamente come gli eventi del mouse?

var isMouseDown = false;  


var panel1 = document.getElementById('panel1'); 
var panel2 = document.getElementById('panel2'); 

panel1.onmousedown = onDocumentMouseDown; 
panel1.onmouseup = onDocumentMouseUp; 
panel1.onmousemove = onDocumentMouseMove; 
panel1.addEventListener('touchstart', onDocumentTouchStart, false); 
panel1.addEventListener('touchmove', onDocumentTouchMove, false); 
panel1.addEventListener('touchend', onDocumentTouchEnd, false); 

panel2.onmousedown = onDocumentMouseDown; 
panel2.onmouseup = onDocumentMouseUp; 
panel2.onmousemove = onDocumentMouseMove; 
panel2.addEventListener('touchstart', onDocumentTouchStart, false); 
panel2.addEventListener('touchmove', onDocumentTouchMove, false); 
panel2.addEventListener('touchend', onDocumentTouchEnd, false); 



function onDocumentMouseDown(event) { 
    event.preventDefault(); 
    panel1.style.background="#2E442E"; 
    panel2.style.background="#5D855C";  
} 

function onDocumentMouseUp(event) { 
    event.preventDefault(); 
    this.style.background="#ff0000"; 
} 

function onDocumentMouseMove(event) { 

} 

function onDocumentTouchStart(event) { 
    event.preventDefault(); 
    panel1.style.background="#2E442E"; 
    panel2.style.background="#5D855C"; 

} 

function onDocumentTouchMove(event) {  

} 

function onDocumentTouchEnd(event) { 
    event.preventDefault();   
    this.style.background="#ff0000";   

} 
+0

quali dispositivi touch hai provato (significa) – shareef

+0

** Domanda simile ** [Come scoprire l'evento.target effettivo dell'evento javascript touchmove?] (Http://stackoverflow.com/q/3918842/351708) – Rohit

risposta

11

Questa era una domanda divertente da affrontare. Grazie per quello. Ecco cosa ho fatto. Ho modificato il vostro gestore touchmove come tale:

function onDocumentTouchMove(event) { 
    onDocumentTouchMove.x = event.changedTouches[event.changedTouches.length - 1].clientX; 
    onDocumentTouchMove.y = event.changedTouches[event.changedTouches.length - 1].clientY; 
} 

In questo gestore Sto salvando l'ultima coordinata che l'utente si trasferisce a. Con tutta probabilità, questo è il punto in cui l'utente ha tolto il dito, il naso, la nocca, lo stilo, ecc. Dalla superficie tattile. Queste coordinate vengono quindi utilizzate nel gestore per touchend per trovare l'elemento che le circonda.

function onDocumentTouchEnd(event) { 
    event.preventDefault(); 
    var elem = document.elementFromPoint(onDocumentTouchMove.x, onDocumentTouchMove.y); 
    elem.style.background = "#ff0000"; 
} 

ho utilizzato il document.elementFromPoint(mdn link) per questo scopo. È uno di quei metodi d'oro ancora abbastanza sconosciuti forniti dallo CSSOM spec.

Ecco lo fiddle.

+1

Grande scoperta! Posso confermare che funziona su un Samsung Galaxy Tab con Chrome. –

+0

Funziona anche su opera, browser Android e Chrome sulla mia x. – zeusdeux

+0

sì .. penso che questa sia una buona soluzione .. :) ma non so quale supporto per elementFromPoint .. – Sarath

-1

Forse, se è possibile includere jQuery nel vostro programma si può fare qualcosa di simile:

$('#itemId').on('touchEnd',function(){ this.trigger('mouseUp') }); 

io non sono sicuro se jQuery fuori dalla scatola supporta questi eventi, ma si può sempre prova jQuery movil, spero che abbia aiutato

+0

no non posso includere jquery ... ma anche questo darà lo stesso risultato .. – Sarath

+0

@isaac 'questo 'qui sarà ancora l'elemento in cui è stato attivato' touchstart', quindi non è una soluzione praticabile. – zeusdeux

0

Da quello che sembra, questo è il comportamento previsto per gli eventi di tocco. Tuttavia, ho una soluzione!

Non l'ho testato estesamente, ma sembra funzionare su Safari mobile per almeno touchStart e touchEnd eventi.

Fondamentalmente quello che stiamo per fare è catturare tutti gli eventi tattili sul documento mentre sono in fase di acquisizione (vedere http://www.w3.org/TR/DOM-Level-3-Events/). Il gestore di questi eventi trova l'elemento DOM in questa posizione e invia nuovamente l'evento con l'obiettivo "corretto".

Sembra che la posizione degli eventi touchEnd non sia ben definita, quindi ho dovuto interrogare l'array changedEvents per ottenere l'ultima posizione toccata. Non sono sicuro che funzioni così come per gli eventi touchMove e così via.

function rerouteTouch (evt) { 
    if (evt.passthrough) { // Ignore if already rerouted 
     return; 
    } 
    evt.stopPropagation(); 
    var newevt = document.createEvent('TouchEvent'); 
    newevt.initTouchEvent (
     evt.type, 
     evt.bubbles, 
     evt.cancelable, 
     evt.view, 
     evt.detail, 
     evt.screenX, 
     evt.screenY, 
     evt.clientX, 
     evt.clientY, 
     evt.ctrlKey, 
     evt.altKey, 
     evt.shiftKey, 
     evt.metaKey, 
     evt.touches, 
     evt.targetTouches, 
     evt.changedTouches, 
     evt.scale, 
     evt.rotation); 
    newevt.passthrough = true; // Only reroute once 

    var target; 
    var x = (evt.type === 'touchend') ? evt.changedTouches[0].pageX : evt.pageX; 
    var y = (evt.type === 'touchend') ? evt.changedTouches[0].pageY : evt.pageY; 

    if (document !== (target = document.elementFromPoint(x, y))) { 
     target.dispatchEvent(newevt); 
    } 
} 

document.addEventListener('touchstart', rerouteTouch, true); // Third arg is true to indicate capture-phase 
document.addEventListener('touchend', rerouteTouch, true); 

... 

// Your event handlers here 

Ecco un jsfiddle che funziona come previsto su Safari Mobile per me: http://jsfiddle.net/DREer/12/

Problemi correlati