Annoying iOS Safari input issues with workarounds

ios_safari

Applications, either for mobile, tablet and beyond rely mostly on input from the user through forms and although the tools have been around for some time now, to create forms that both improves the UX and works properly is still a tough grind.

For instance in the case of a date picker our goal is to restrict the user to enter the date in a certain format. The user is presented with either entering the date in a given format or choosing a date from a predefined set of values. Also there are cases when to the user is given the opportunity to enter the data in a desired format.

Mobiscroll controls are enhancing data entry and usually don’t allow the user to directly access the fields, the input is set to read-only, this way the chance of error is eliminated. To alleviate the problem of figuring out the multiple possible-entries a couple of event listeners are attached and the UI widget is being shown when the user interacts with the form.

There are 3 events which may trigger the opening of the Mobiscroll widget:

  • touchend (only if no or very little movement has occurred between touchstart and touchend) – Opens the widget when tapping the form input on a touch screen.
  • click – Opens the widget on pointer click (desktop, or hybrid devices).
  • focus – Opens the widget when the navigation between page elements is done with keyboard or assistive technologies (VoiceOver, TalkBack…).

We would like to share with you the issues we encountered and the solutions we have came up with.

The virtual keyboard opening issue

While setting a form input read-only should prevent the virtual keyboard (or other native controls, like a datepicker) from opening, there are some devices, where this still happens:

  • Some Android 2.3 devices (seen on a HTC Desire HD browser, although not consistently reproducible)
  • Older versions of Firefox OS
  • Older versions of Amazon Silk browser
  • iOS8 Safari

Since the mentioned first three events have a very low market share are not really a concern. On the other hand the iOS8 Safari issue is a real deal breaker.
The issues we have found are listed below:

  • When a read-only text input field gets focus, the virtual keyboard does not appear, but a toolbar at the bottom of the screen appears (with < and > buttons, and an extra ‘Done’ button on iPhone/iPod).
  • When a read-only date or time input gets focus, surprisingly the native date or time picker pops up and even allows editing the value of the input. This seems like a major bug, we submitted a ticket to apple when 8.0 was released, but neither an answer, nor a fix was delivered since than.

The virtual keyboard opening happens on the focus event, so one approach to solve the issue is to somehow prevent the firing of the focus event. Calling preventDefault on the mousedown event is well supported way of doing this.

One issue that is still unsolved is that when closing the Mobiscroll widget, the input field should regain the focus from the point of view of accessibility. Unfortunately this action activates the described buggy behavior on iOS8 Safari.

Touch events failing on iOS8

Another bug we discovered during our testing process is that under certain circumstances touch events are simply not firing on form input fields in the case when the app:

  • is a web application and added to the Home Screen
  • has the <meta name=”apple-mobile-web-app-capable” content=”yes”> to hide the native browser controls when opened from the Home Screen

This was tested by using plain javascript code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="msapplication-tap-highlight" content="no" />
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
        <title>iOS Readonly Input Test</title>
 
        <style type="text/css">
            input {
                width: 100%;
                height: 40px;
                margin: 10px 0;
                border-radius: 0;
                -webkit-box-sizing: border-box;
                -webkit-appearance: none;
            }
 
            button {
                width: 100%;
                height: 40px;
                margin: 10px 0;
                -webkit-box-sizing: border-box;
                -webkit-appearance: none;
            }
        </style>
    </head>
    <body>
 
        <input id="test1" readonly />
        <input id="test2" />
        <input id="test3" type="date" readonly />
        <button id="clear">Clear Console</button>
        <div id="console"></div>
 
        <script>
 
            function logEvent(txt) {
                var row = document.createElement('div');
                row.innerHTML = txt;
                console.appendChild(row);
            }
 
            function listenToInput(input, nr) {
                input.addEventListener('touchstart', function () {
                    logEvent('touchstart on input ' + nr);
                });
 
                input.addEventListener('touchend', function () {
                    logEvent('touchend on input ' + nr);
                });
 
                input.addEventListener('mousedown', function (e) {
                    //e.preventDefault();
                    logEvent('mousedown on input ' + nr);
                });
 
                input.addEventListener('mouseup', function () {
                    logEvent('mouseup on input ' + nr);
                });
 
                input.addEventListener('focus', function () {
                    logEvent('focus on input ' + nr);
                });
 
                input.addEventListener('click', function () {
                    logEvent('click on input ' + nr);
                });
            }
 
            var console = document.getElementById('console'),
                input1 = document.getElementById('test1'),
                input2 = document.getElementById('test2'),
                input3 = document.getElementById('test3'),
                btn = document.getElementById('clear');
 
            listenToInput(input1, 1);
            listenToInput(input2, 2);
 
            btn.addEventListener('click', function () {
                console.innerHTML = '';
            });
        </script>
    </body>
</html>

Fortunately we discovered that this issue is not present in the web browser, nor in the WebView.

The mousedown, mouseup, focus and click events are still firing. So the Mobiscroll widget will still appear, as it has the click event attached, but with the ~300 milliseconds latency of the emulated mouse events, making the app feel less snappy.

While testing the same issue with Ionic Framework we discovered that the content is scrolled using a custom scroll engine instead of the native browser scroll. Also in this scenario even the click events are not consistently fired, resulting in a frustrating user experience.

At this time the only possible workaround is to get rid of the actual input field, and use a div element that is styled to look like an input field and if needed, additionally store the value in a hidden input field. The content (“value”) of the div element should also be maintained.
Below we give you a sample implementation with Mobiscroll:

1
2
3
4
5
6
7
8
9
10
11
12
<div id="mydate" class="custom-input">12/24/2014</div>
<input id="mydateinput" type="hidden" />
 
<script>
$('#mydate').mobiscroll().date({
   defaultValue: new Date(2014, 11, 24),
   onSelect: function (valueText) {
       $(this).html(valueText);
       $('#mydateinput').val(valueText).change();
   }
});
</script>

We know that fixing technical issues on mobile is annoying so we expect that in the near future these issues will be resolved and we can take our form inputs for granted.
Until than let’s appeal to these handy practices.


What is your experience or frustration with browser inconsistencies? Let us know in the comments below!

Start building better products
Sign up and get posts like this in your inbox. We respect your time and will send you only the good stuff!

Tags: , , , ,

  • Right here is the perfect web site for anyone who hopes
    to understand this topic. You understand a whole lot its
    almost hard to argue with you (not that I really will need to…HaHa).
    You certainly put a fresh spin on a topic that has been written about for decades.
    Excellent stuff, just wonderful!