2015-03-12 15 views
7

Próbuję utworzyć zdarzenie dotyku dla testu jednostki. Po przeczytaniu https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent, spodziewałem się, że będę w stanie to zrobić:Jak programowo utworzyć TouchEvent w przeglądarce Chrome 41?

document.createEvent('TouchEvent'); 

Ale otrzymuję ten błąd:

Uncaught DOMException: Failed to execute 'createEvent' on 'Document': The provided event type ('TouchEvent') is invalid.

widziałem Creating and firing touch events on a touch enabled browser?, który również wydaje się wskazywać, że CreateEvent() jest droga iść.

Próbowałem też tworząc wydarzenie za pomocą konstruktora, który pracuje dla, powiedzmy, MouseEvent i WheelEvent:

new window.TouchEvent() 

Ale pojawia się błąd i tu:

Uncaught TypeError: Illegal constructor

Próbowałem w Firefoksie 36, ale na podstawie http://caniuse.com/#search=touch, nie byłem zaskoczony, aby zobaczyć:

NotSupportedError: Operation is not supported

Po ru nning

document.createEvent('TouchEvent') 

Nie ma zdarzenia window.TouchEvent konstruktora w Firefoksie, co znowu nie jest zaskakujące.

Jakieś pomysły, co robię źle?

Odpowiedz

3

Wygląda

document.createEvent('TouchEvent'); 

robót jeśli używasz rzeczywistego urządzenia mobilnego lub emulacji mobilnego.

+0

(tylko Windows 8+) Jeśli nie masz rzeczywistego urządzenia, możesz utworzyć program wywołujący [InitializeTouchInjection] (https: // msdn .microsoft.com/en-us/library/windows/desktop/hh802880 (v = vs.85) .aspx). Stworzy to wirtualne urządzenie dotykowe, które Chrome rozpoznaje i pozwala tworzyć TouchEvents. –

2

Zgaduję, że jedynym sposobem, aby to zrobić bez rzuca wyjątek ma być bardziej wyraźne w rodzaju zdarzenia, które chcesz utworzyć:

var evt = document.createEvent('UIEvent'); 

evt.initUIEvent('touchstart', true, true); 

TouchEvent jest podklasą UIEvent.

Aktualizacja

Jak wspomniano powyżej, w czasie rzeczywistym urządzenia (lub do emulacji urządzenia), można łatwo stworzyć TouchEvent za pomocą standardowej metody document.createEvent.

Więc być może try/catch byłoby w porządku:

try { 

    document.createEvent('TouchEvent'); 

} catch (e) { 

    console.log('No touching!'); 

} 
+0

Myślałem o tym, ale miałem nadzieję, że będę zależał od rodzaju obiektu; Przeprowadzamy syntezę zdarzeń, a także używając narzędzia HammerJS, więc wiele klas zdarzeń ma ten sam typ, na przykład "touchstart". Z pewnością mógłbym użyć UIEvent, aby mój test minął, ale nie miałby on właściwego ducha testu. :) – exavatar

+0

Czy rzeczywiście istnieje taka różnica między 'evt.constructor == TouchEvent' i' /touch/.test (evt.type) '? JavaScript naprawdę nie zajmuje się dziedziczeniem klasycznym, więc IMO próbujesz dopasować kwadratowy kołek do okrągłej dziury - nawet jeśli jest porywający :-) – shennan

+0

Nie, niezbyt duża różnica, poza wygaśnięciem zdarzenia.typ będzie nie pasuje do kodu, który próbuję przetestować; Być może będę musiał to zmienić. – exavatar

2

Aktualizacja: To nie będzie faktycznie spowodować wystąpienie TouchEvent. kulawy.

zrobiłem to tak:

var type = 'start'; // or move, end 
var event = document.createEvent('Event'); 
event.initEvent('touch' + type, true, true);  
event.constructor.name; // Event (not TouchEvent) 

Będziesz także musiał ustawić akcenty na imprezy. To kolejna puszka robaków, ponieważ niektóre przeglądarki obsługują metody document.createTouch i document.createTouchList, a niektóre nie. W przeglądarkach, które nie tworzą po prostu tablicy obiektów JS, które są "podobne do TouchEvent". To wygląda tak:

var point = {x: 10, y: 10 }; 
event.touches = [{ 
    target: someElement, 
    identifier: Date.now() + i, 
    pageX: point.x, 
    pageY: point.y, 
    screenX: point.x, 
    screenY: point.y, 
    clientX: point.x, 
    clientY: point.y 
}] 
+0

Wygląda na to, że zarówno ty, jak i shennan stosujesz to samo podejście i doceniam pomoc. Jest to obejście, a nie dokładnie to, nad czym pracuję. Ale może utknąłem z tym. – exavatar

+0

Co do aktualizacji: Tak, to jest problem. Chcę instancji TouchEvent, aby nie polegać na liście zdarzeń.type – exavatar

8

Nie wiem, czy to działa w innych przeglądarkach, ale w Chrome można zrobić coś podobnego

/* eventType is 'touchstart', 'touchmove', 'touchend'... */ 
function sendTouchEvent(x, y, element, eventType) { 
    const touchObj = new Touch({ 
    identifier: Date.now(), 
    target: element, 
    clientX: x, 
    clientY: y, 
    radiusX: 2.5, 
    radiusY: 2.5, 
    rotationAngle: 10, 
    force: 0.5, 
    }); 

    const touchEvent = new TouchEvent(eventType, { 
    cancelable: true, 
    bubbles: true, 
    touches: [touchObj], 
    targetTouches: [], 
    changedTouches: [touchObj], 
    shiftKey: true, 
    }); 

    element.dispatchEvent(touchEvent); 
} 

const myElement = document.getElementById('foo') 

sendTouchEvent(150, 150, myElement, 'touchstart'); 
sendTouchEvent(220, 200, myElement, 'touchmove'); 
sendTouchEvent(220, 200, myElement, 'touchend'); 

Aby sprawdzić, czy dana przeglądarka obsługuje Touch i TouchEvent

if (typeof Touch !== 'undefined' && 
    typeof TouchEvent !== 'undefined' && 
    Touch.length === 1 && 
    TouchEvent.length === 1) { 
     sendTouchEvent(200, 200, myElement, 'touchmove'); 
} 

zobaczyć Touch and TouchEvent constructors

+0

Dzięki. To jest aktualna poprawna odpowiedź. Działa w Chrome 56. – ElDog

+0

To wygląda dobrze, ale nie działa dla mnie: Nie mogę utworzyć obiektu Touch w taki sposób, w jaki to robisz ("Podane parametry nie pasują do sygnatury docelowej połączenia"), ponieważ es6 zadeklarowało to w ten sposób: 'declare var Touch: {prototype: Touch; new(): Dotknij; }; '. Z jakiej wersji korzystasz? –

+1

@MichaSchwab Właśnie przetestowałem fragment na chromie 59 i nadal działa. Pamiętam, że miałem ten sam problem w maszynopisie (powinienem wypełnić problem). Ogłosiłem swój własny interfejs, aby temu zapobiec. Możesz go znaleźć [tutaj] (https://github.com/fhdhsni/weewikipaint/blob/master/src/scripts/globals.d.ts#L24-L32) i [tutaj] (https://github.com /fhdhsni/weewikipaint/blob/master/test/client/sendEvent.ts) – fhdhsni

Powiązane problemy