Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable iOS "Shake to Undo" in a webapp

I'm building a game as a webapp for the iPad. It incorporates a shake action to trigger an event for one of the screens, but, since it also has a information collection form, sometimes that shake action triggers the annoying "Shake to Undo" dialog. The form input the user has typed in don't even exist in the DOM anymore when the user reaches the shake action, so in my mind the Undo function shouldn't be triggered, but unfortunately it is. There is no way this can be wrapped in a native wrapper (PhoneGap or other), so I was wondering if anyone knows if it's at all possible to disable this functionality for a specific web page/app, through CSS or JavaScript?

Thanks.

like image 298
Johan Sahlén Avatar asked Jun 29 '11 11:06

Johan Sahlén


People also ask

What is shake in Iphone accessibility?

With Shake to Undo turned on, iOS users can quickly fix mistakes, such as shake to undo typing in a text, shake to undo archiving an email, shake to undo typing in the Notes app.


2 Answers

For PhoneGap I just inserted this line: [UIApplication sharedApplication].applicationSupportsShakeToEdit = NO; in the webViewDidFinishLoad class and it worked wonders for me.

Just go to the MainViewController.m and change webViewDidFinishLoad to look like this:

- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{
    // Black base color for background matches the native apps
    theWebView.backgroundColor = [UIColor blackColor];

[UIApplication sharedApplication].applicationSupportsShakeToEdit = NO;

    return [super webViewDidFinishLoad:theWebView];
}
like image 146
Tobias Christian Jensen Avatar answered Sep 27 '22 19:09

Tobias Christian Jensen


I found a workaround that works consistently: you can host the text input in a frame. When you're done with the input, remove the frame from the page. This seems to do the trick.

function resetIframe() {
  // Remove the old frame
  document.body.removeChild(frame);

  // Create a new frame that has an input internally
  frame = document.createElement('iframe');
  frame.src = '/html-with-input.html';
  frame.style = 'border: 0; height: 30px; width: 200px;'
  document.body.appendChild(frame);

  // When the frame is ready, grab a reference to the input
  frame.addEventListener('load', () => {  
    const input = frame.contentDocument.body.querySelector('input');
    console.log(frame, frame.contentDocument.body)

    // When the input changes, grab the value
    input.addEventListener('input', e => {
      document.getElementById('output').innerText = e.target.value;
    });
  });
}

Here's a proof of concept: https://codepen.io/joshduck/full/RJMYRd/

like image 26
Josh Duck Avatar answered Sep 27 '22 19:09

Josh Duck