34

I searched for the past 30 minutes, but didn't find a solution.

I want to trigger a touchstart event on an element.

This fires the touchstart event:

var e = document.createEvent('MouseEvent');

e.initMouseEvent("touchstart", true, true, window, 1, screenX, screenY, clientX, clientY,
    ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);

target.dispatchEvent(e);

Note that the variables are defined by my function

But there's a problem with that. The event object doesn't have a touches property. So something like this won't work:

var touch = e.touches[0];

Is there a way to trigger a touchstart event manually (it should work on Android >= 4.0 and Chrome with touch enabled [DevTools]) ?

Please note, that I do NOT want to use any framework like jQuery. With jQuery it's easy to create a touchevent on an element ;)

AndreM96
  • 1,355
  • 1
  • 23
  • 34
  • 1
    Just for sanity, why do you need to generate an event? – Halcyon Aug 05 '13 at 13:51
  • Well, lets say that I have a container. This container has many subcontainer which are hidden. When I touch on this container, one subcontainer becomes visible, and as long as I touch the container, I should be able to move the subcontainer by moving my finger. So when I touch on the container, a `touchstart` event should be created on the subcontainer. – AndreM96 Aug 05 '13 at 13:56
  • 1
    That sounds like something that should be fairly easy to do without faking events. If your model knows about the container dependency you can control all from the single original event. – Halcyon Aug 05 '13 at 14:00
  • 1
    Well, it's a bit more complicated and I can't do it your way :/ I have to fake the event... – AndreM96 Aug 05 '13 at 14:05

5 Answers5

25

According to W3C

var e = document.createEvent('TouchEvent');

Then, also change

e.initMouseEvent();

to

e.initTouchEvent();

As you've created a touchstart event.

The W3C link says:

Some user agents implement an initTouchEvent method as part of the TouchEvent interface. When this method is available, scripts can use it to initialize the properties of a TouchEvent object, including its TouchList properties (which can be initialized with values returned from createTouchList). The initTouchEvent method is not yet standardized, but it may appear in some form in a future specification.

So you'll might have to resort to e.initUIEvent('touchstart', true, true);
In addition, the official spec also states that the TouchList object is optional, and can be created manually using the createTouchList method. To add a touch to that list, you'll have to call the createTouch method, where you'll pass all coordinates and such:

6.1 Methods

#createTouch
Creates a Touch object with the specified attributes.
Parameter | Type        | Nullable | Optional | Description
view      | WindowProxy |   ✘      |    ✘     |
target    | EventTarget |   ✘      |    ✘     |
identifier| long        |   ✘      |    ✘     |
pageX     | long        |   ✘      |    ✘     |
pageY     | long        |   ✘      |    ✘     |
screenX   | long        |   ✘      |    ✘     |
screenY   | long        |   ✘      |    ✘     |
Return type: Touch

#createTouchList
Creates a TouchList object consisting of zero or more Touch objects. Calling this method with no arguments creates a TouchList with no objects in it and length 0 (zero).

Parameter | Type  | Nullable | Optional | Description
touches   | Touch |     ✘    |    ✔     |
Return type: TouchList

If that doesn't work, you could try this:

var e = document.createEvent('UIEvent');
e.initUIEvent();

should work, it makes more sense than createEvent('MouseEvent') at any rate...
But for testing purposes, why not open your chrome console and check Emulate touch events, plus override user agent to Android 4. (Ctrl+Shift+j > click the gear bottom right corner, and select Overrides, there you'll find all the settings you need)

Since the touch-events have a long way to go, still in terms of their becoming standardized, it turns out the touches property is not RO (yet?), so you can use this quick-fix (which the OP found and used with the desired result):

var e = document.createEvent('TouchEvent');
e.touches = [{pageX: pageX, pageY: pageY}];

Which, I think (I can't believe it if it weren't the case) is faster than:

e.touches = e.createTouchList(
    e.createTouch(window, target, 0, pageX, pageY, screenX, screenY)
);
Konrad Dzwinel
  • 36,825
  • 12
  • 98
  • 105
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • First, thank you for this answer! :) I have tried that, too, but it didn't work... There's no good documentation on `createEvent('TouchEvent')`. :/ And in Chrome I get this error: `Uncaught Error: NotSupportedError: DOM Exception 9`. And with `[DevTools]` in my question I meant that I had dev tools touch enabled. ;) – AndreM96 Aug 05 '13 at 14:03
  • 2
    @AndreM96: Found it: the `TouchList` object is optional, and you'll have to manually create a `Touch` object using the `createTouchList` and `createTouch` methods respectively – Elias Van Ootegem Aug 05 '13 at 14:09
  • Thanks! That works. I found a simple workaround which I now use: `e.touches = [{pageX: pageX, pageY: pageY}];` (`e` is the created event). But your solution is definitely better! – AndreM96 Aug 05 '13 at 14:21
  • 2
    @AndreM96: I wouldn't say that, if passing an object literal works just as well, then your sollution is probably the one to go for. An object literal is cheap and fast, while the DOM is bulky, counter intuitive, and often slow, so I'll edit my answer and include your workaround – Elias Van Ootegem Aug 05 '13 at 14:24
  • @EliasVanOotegem These methods `createTouchList` have been deprecated so I am unable to use your suggestion. – tusharmath Nov 30 '16 at 18:59
  • Few problems with this: a) e.touches may be not overridable for touch event (so in Phantom 2.1), b) createEvent('TouchEvent'), createTouch etc. are not supported in most current browsers (Chrome, FF). Chrome seems to implement support for Level 2 touch events (https://w3c.github.io/touch-events/) so you can use constructors to construct events, but it is only Chrome. – Georgii Ivankin May 03 '17 at 22:08
  • @GeorgiiIvankin I'm sorry, but really: look at how old this answer is: 2013. Almost 4 years ago, `createEvent` was *not* deprecated, [as it is today](https://developer.mozilla.org/en-US/docs/Web/API/Document/createEvent). If things have changed, which they have, it might be worth while updating an existing/accepted answer. I've moved on to back-end development only. I can't keep answers like this up to date. – Elias Van Ootegem May 05 '17 at 23:58
  • 1
    @EliasVanOotegem nothing personal, didn't mean you were wrong. It's just that I feel too busy to properly update the answer and instead leave the comment so that it might be useful to those who find this answer. – Georgii Ivankin May 18 '17 at 01:38
20

I know this has been answered, but I too struggled to find an answer to this problem and the accepted answer didn't work for me. In the end, the solution I found is really very simple and has support across browsers:

var e = new Event('touchstart');
target.dispatchEvent(e);

That's it. Couldn't be easier.

Derek Henderson
  • 9,388
  • 4
  • 42
  • 71
5

I have come up with this solution (javascript native), works for me

var el = document.getElementById('myDivId');
// desktop
el.click();

// mobile
if (window.matchMedia("(max-width: 768px)").matches) {
        // createEvent(), event.initEvent() are Depricated see Ref: [enter link description here][1]
        // var event = document.createEvent("Event"); 
        // event.initEvent("touchstart", false, true);
        // event.initEvent("touchend", false, true);
        // So the solution is:
        var event1 = new Event('touchstart');
        var event2 = new Event('touchend'); 
        el.dispatchEvent(event1); 
        el.dispatchEvent(event2);
  }
Theva
  • 873
  • 8
  • 15
4

In 2019, we can use TouchEvent and Touch.

Touch is an experimental technology

For example,

const touch = new Touch({
  identifier: "123",
  target: target,
});

const touchEvent = new TouchEvent("touchstart", {
  touches: [touch],
  view: window,
  cancelable: true,
  bubbles: true,
});

target.dispatchEvent(touchEvent);

I created gist. try it simple.

Chase Choi
  • 882
  • 11
  • 25
  • Hm. I can't seem to get your gist to work; I put it in a CodeSandbox at https://codesandbox.io/s/simulatetouchevent-test-i0vzx?file=/src/index.js Is there something I'm missing? – Dan Overlander Apr 20 '20 at 18:56
  • @DanOverlander You added `click` event on the element. `click` and `touch` are different. If you replace `click` to `touchstart` or `touchend` it'll work as epxected. – Chase Choi Apr 21 '20 at 04:17
  • giving me error on chrome : Cannot set property touches of # which has only a getter – user889030 May 24 '21 at 07:26
  • 1
    @user889030 could you share your code? my working fiddle is https://jsfiddle.net/3qubaek0/ – Chase Choi May 24 '21 at 08:15
  • @ChaseChoi thanks your fiddle is working ok looks like there was issue in my code i updated it according to your fiddle now its working ok . many thanks – user889030 Jun 06 '21 at 09:20
  • @ChaseChoi if you not mind can i share my code with you , am struggling with one webpage canvas am not able to trigger touch on it although it should be working ok as you demo in jsfiddle snippet. struggling my head from week with it but no clue why its not working :( – user889030 Jun 06 '21 at 09:24
  • @user889030 Sure, but not sure I'm able to fix it. – Chase Choi Jun 09 '21 at 01:29
-5

We can trigger like this:

$playBtn.bind((is_touch_device) ? 'touchstart' : 'click', playfunction);
Praveen
  • 113
  • 6
  • 3
    Please, check the short description of the JavaScript tag: _"Unless a tag for a framework/library is also included, a pure JavaScript answer is expected"_, just hover your mouse over it. There is no jQ tag, no jQ answers... – Elias Van Ootegem Aug 05 '13 at 13:56
  • 1
    I just updated my question. Yes, I don't want to use any kind of framework. ;) – AndreM96 Aug 05 '13 at 13:58