Opened 7 years ago

Closed 7 years ago

Last modified 6 years ago

#16730 closed defect (fixed)

ComboBox: long drop down lists broken on iOS

Reported by: bill Owned by: Douglas Hays
Priority: undecided Milestone: 1.7.6
Component: Dijit - Form Version: 1.8.3
Keywords: Cc: cjolif
Blocked By: Blocking:

Description

A number of problems with ComboBox on iPad:

  1. The virtual keyboard covers up the bottom of the drop down list.
  2. clicking an item in the drop down list makes the screen jump (i.e. scroll)
  3. You cannot scroll the drop down list.

I'll check in a fix for the first problem. Doug should probably handle the second two.

The first problems requires place.js and _HasDropDown.js to estimate how much of the screen is covered up by the virtual keyboard, and calculate the size of the effective viewport.

The second problem, the jumping problem, is caused by the scrollIntoView() call in _ListBase::_setSelectedAttr(). That should probably only happen on keyboard select, not on selection by mouse or touch. Either that or fix scrollIntoView() so it doesn't get confused when the virtual keyboard is popped up?

The third problem, where you can't scroll, is caused by the evt.preventDefault() calls in _ListBase::_listConnect() and _ListMouseMixin::postCreate(). evt.preventDefault() on touchstart prevents native scrolling.

Attachments (4)

16730.patch (2.0 KB) - added by Douglas Hays 7 years ago.
ComboBox? scrolling fix on IOS
Tooltip-iPad1-iOS5.PNG (56.3 KB) - added by Sebastien Brunot 7 years ago.
Tooltip problem on iOS
viewport.patch (2.0 KB) - added by Sebastien Brunot 7 years ago.
Fix viewport calculations on iOS (IBM CCLA).
readOnlyFocusedNode.patch (672 bytes) - added by Sebastien Brunot 7 years ago.
Do not adapt the height of the viewport on iOS if the focusedNode is read only (IBM CCLA).

Download all attachments as: .zip

Change History (48)

comment:1 Changed 7 years ago by bill

In [30616]:

Account for space used by iOS virtual keyboard into account when displaying drop downs / popups. Refs #16730 !strict.

Git: a7e93cbc539a55918c774f2d031025cc22f6fab7

Last edited 6 years ago by bill (previous) (diff)

comment:2 Changed 7 years ago by bill

In [30619]:

Just monitor focus directly rather than introducing dependency on dijit/focus. Also, move definition of getEffectiveBox() outside of domReady() to prevent exception on page load during dijit/place test. Refs #16730 !strict.

Git: 4be135733e99980f17e2ff28b1ade31701023d08

Last edited 6 years ago by bill (previous) (diff)

comment:3 Changed 7 years ago by bill

In [30621]:

fix detection of focus on textarea nodes, although we never have popups/dropdowns from a textarea, refs #16730 !strict.

Git: 16a92a3f0c5fb6e18c3e58ea1e7099f6fb9e0696

Last edited 6 years ago by bill (previous) (diff)

Changed 7 years ago by Douglas Hays

Attachment: 16730.patch added

ComboBox? scrolling fix on IOS

comment:4 Changed 7 years ago by Douglas Hays

Milestone: tbd1.9
Status: newassigned

comment:5 Changed 7 years ago by Douglas Hays

Resolution: fixed
Status: assignedclosed

In [30627]:

Fixes #16730. Have ComboBoxMenu? trap mouse events and not touch events so that touch scrolling works. Monitor click events and collapse redundant faux and real click events.

Git: 4cdad4262819979837e8a84425c9f1e2a5efe6a5

Last edited 6 years ago by bill (previous) (diff)

comment:6 Changed 7 years ago by bill

Resolution: fixed
Status: closedreopened

[30627] breaks the regression tests for !ComboBox_menu and !FilteringSelect_menu. Tested on IE8.

comment:7 Changed 7 years ago by bill

In [30661]:

Refactor TimePicker to be a traditional drop down list with a scrollbar, like ComboBox. Fixes #7631, #14719 !strict, and refs #8387, #16730 tangentially. Note that the visibleRange option is no longer supported, as it no longer makes sense. If specified, it will be ignored.

comment:8 Changed 7 years ago by Douglas Hays

Resolution: fixed
Status: reopenedclosed

In [30665]:

Fixes #16730. The fix was good but it uncovered an existing problem with setTimeout (via defer) in IE8. A setTimeout callback can fire even after a clearTimeout.

Git: 113fbdf0de8e68e75d454de0ca24e68a67f459cd

Last edited 6 years ago by bill (previous) (diff)

comment:9 Changed 7 years ago by bill

#16335 is a duplicate of this ticket.

comment:10 Changed 7 years ago by bill

In [30697]:

fix exception on FF where focusedNode can be "document", in which focusedNode.tagName is undefined, refs #16730 !strict

Git: b5d62d0a4f1f08b6e0d9ab3752c4d92a59aad5cc

Last edited 6 years ago by bill (previous) (diff)

comment:11 Changed 7 years ago by Alexander Kläser

I just tried the SVN implementation, it seems to work in my case (Asus Transformer tablet), the virtual keyboard does not appear and browsing in the list works fine. However, I cannot simply open the list through tapping on the arrow (this is what I would expect), instead the focus would go into the textbox.

Last edited 7 years ago by Alexander Kläser (previous) (diff)

comment:12 Changed 7 years ago by Alexander Kläser

I implemented the following workaround in a custom combo box class, this would be the behaviour I would expect from touch devices:

// ...

// monitor the last clicked DOM node... for special handling of touch devices
var clickedNode = null;
aspect.before(dijit_focus, '_onTouchNode', function(node, by) {
    clickedNode = node;
    return [node, by];
});

return declare('MyComboBox', [ dijit_form_FilteringSelect ], {
    // ...

    _firstClick: true,

    _onFocus: function() {
        if (has('touch')) {
            // special handling for touch devices...
            var isButtonClicked = dojo_dom.isDescendant(clickedNode, this._buttonNode);
            if (!this.textbox.disabled && (this._firstClick || isButtonClicked)) {
                // disable focusing the input box on touch devices
                // in order to avoid the keyboard from showing
                this.textbox.disabled = true;
                if (this._firstClick && !isButtonClicked) {
                    this.toggleDropDown();
                }
                this._firstClick = false;
                setTimeout(lang.hitch(this, function() {
                    this.textbox.disabled = false;
                    clickedNode = null;
                }), 1000);
            }
        }
        this.inherited(arguments);
    }
});

comment:13 in reply to:  11 ; Changed 7 years ago by bill

Replying to alexklaeser:

I just tried the SVN implementation, it seems to work in my case (Asus Transformer tablet), the virtual keyboard does not appear and browsing in the list works fine. However, I cannot simply open the list through tapping on the arrow (this is what I would expect), instead the focus would go into the textbox.

Works for me, running dijit/tets/form/mobile.html on my iPad, trying the second widget under the heading "Selects".

comment:14 in reply to:  13 Changed 7 years ago by Alexander Kläser

Replying to bill:

Works for me, running dijit/tets/form/mobile.html on my iPad, trying the second widget under the heading "Selects".

I tried it at http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/form/mobile.html ... it works great on my iPad, as well, however, it does not work on the Asus transformer. The textbox still gets focussed.

comment:15 Changed 7 years ago by Paul Christopher

Strange, I have tested this in my iPad2, too. When running dijit/tests/form/mobile.html, sometimes it works great and sometimes the keyboard is shown although I really do try hard just to hit the arrow button only. So I could partially reproduce Alex's issue. Can you reproduce it too, Bill? Just try the reload the page several times. Click the first select, then the second. Sometimes the keyboard shows up. The desired behaviour seems not to be stable.

comment:16 Changed 7 years ago by Paul Christopher

Some other remarks on dijit/tests/form/mobile.html

-- DateTextBox: Opening just the calender with the drop down button works perfectly. The keyboard is not shown (Why? It's just a _HasDropDown, too?). However if you click somewhere else on the screen so as to close the calendar widget (which is the usual way on the iPad to close a widget), the textbox is focused and thus the keyboard is shown. Also when choosing an entry from the calendar, the calendar drop down is closed but the textbox focused. Maybe it would be nicer to prevent focusing after choosing a value from the calendar?

-- TimePicker: Shows the same effects as the ComboBox: Clicking on the drop down button opens the drop down but also sometimes focuses the input field. However opening the drop down and clicking somewhere else so as to close it, does not focus the textbox (in contrast to DateTextBox).

-- The NumberSpinner is barely usable for my thick fingers ;-)

comment:17 Changed 7 years ago by bill

Paul and Alex - By dijit's design, whenever you click the down arrow on a widget, focus goes somewhere. Either to the dropdown, or if the dropdown isn't focusable, to the textbox. That's why DateTextBox is different than FilteringSelect, because the Calendar is focusable but the FilteringSelect drop down is (by design) not focusable. On mobile devices, by design, the keyboard gets shown whenever a textbox is focused, and hidden whenever the textbox is blurred.

I realize the combination of those designs is suboptimal for mobile, especially small screens, but that's the way dijit is currently designed. Note the dijit bends over backwards to be completely accessible for desktop users that can only use a keyboard, which is why focus always goes somewhere, although admittedly it's overkill to set focus due to a mouse click or touch event.

So if anything the remaining bugs (possibly related) are that

  1. You sometimes need to click the arrow twice to show the drop down list.
  2. The ComboBox textbox sometimes doesn't get focus on mobile by clicking the down arrow. Or from the alternate angle (as an enhancement request), pressing the down arrow shouldn't focus anything.

Anyway, at least ComboBox is usable, which was the focus of this ticket. Or did I miss something? Is it completely unusable on your Asus Transformer tablet, and if so what is the version of android on that tablet?

PS: I agree that NumberSpinner is badly designed for mobile. On mobile it should use dojox/mobile's Spinner code, to look like the native mobile spinners. Something for 2.0.

comment:18 Changed 7 years ago by bill

PPS: I see Alex's code above avoids focusing the textbox on mobile. Probably what we need though is to differentiate from clicking the textbox vs. clicking the down arrow. Clickin the textbox should focus the textbox; otherwise the app might as well just use dijit/Select instead of dijit/FilteringSelect.

Or perhaps I misunderstood your patch?

comment:19 Changed 7 years ago by Paul Christopher

On the iPad, concerning focusing behaviour, I think there is a difference whether you run dijit/tests/form/mobile.html in the browser or as web app from the home screen. In normal browser mode, someNode.focus() does not work in most cases, see http://stackoverflow.com/questions/9905888/how-to-change-the-input-focus-on-a-tablet-with-js. But my experience is, in web app mode, focusing a node works again. At least my impression is, that when running dijit/tests/form/mobile.html in web app mode, clicking on the arrow button always opens the keyboard (as Alex has reported it for the Android tablet)?

comment:20 Changed 7 years ago by bill

Interesting link. I can't imagine why launching the web page from the a shortcut on the home screen would make a difference (it's still running in safari, right?), but I guess regardless of that, the issue would be to stop dijit from calling focus() unnecessarily.

comment:21 in reply to:  18 ; Changed 7 years ago by Alexander Kläser

Replying to bill:

Paul and Alex - By dijit's design, whenever you click the down arrow on a widget, focus goes somewhere. Either to the dropdown, or if the dropdown isn't focusable, to the textbox. That's why DateTextBox is different than FilteringSelect, because the Calendar is focusable but the FilteringSelect drop down is (by design) not focusable. On mobile devices, by design, the keyboard gets shown whenever a textbox is focused, and hidden whenever the textbox is blurred.

I realize the combination of those designs is suboptimal for mobile, especially small screens, but that's the way dijit is currently designed. Note the dijit bends over backwards to be completely accessible for desktop users that can only use a keyboard, which is why focus always goes somewhere, although admittedly it's overkill to set focus due to a mouse click or touch event.

So if anything the remaining bugs (possibly related) are that

  1. You sometimes need to click the arrow twice to show the drop down list.
  2. The ComboBox textbox sometimes doesn't get focus on mobile by clicking the down arrow. Or from the alternate angle (as an enhancement request), pressing the down arrow shouldn't focus anything.

Anyway, at least ComboBox is usable, which was the focus of this ticket. Or did I miss something? Is it completely unusable on your Asus Transformer tablet, and if so what is the version of android on that tablet?

Thanks for your clarification, Bill. I do not have the Asus Transformer tablet at hand this week… will check it again next week. AFAIR the usability was ok, except the fact that the keyboard opens up.

Replying to bill:

PPS: I see Alex's code above avoids focusing the textbox on mobile. Probably what we need though is to differentiate from clicking the textbox vs. clicking the down arrow. Clickin the textbox should focus the textbox; otherwise the app might as well just use dijit/Select instead of dijit/FilteringSelect.

Or perhaps I misunderstood your patch?

Yes, this is what I wanted to achieve, a different behaviour for clicking on the textbox vs. clicking on the arrow. Regarding dijit's focus policy, would it make sense to focus the drop down list when clicking on the arrow? This would comply with dijit's focus policy (something needs to be focused) and would also be intuitive for desktop and mobile users.

What would then happen, e.g., to a dialog containing a form with a FilteringSelect and being focussed upon opening? If I see it corretly, the FilteringSelect's textbox would be focussed and the keyboard would open, right? Hm… does it make sense to expect a different default focus behaviour on desktop and on mobile? In other words, focussing the FilteringSelect on a desktop platform would focus the textbox, and focussing the FilteringSelect on a mobile platform would (open and) focus the drop down list (explicitly touching on the textbox would focus the textbox and open the keyboard, of course)?

comment:22 in reply to:  21 ; Changed 7 years ago by bill

Replying to alexklaeser:

Yes, this is what I wanted to achieve, a different behaviour for clicking on the textbox vs. clicking on the arrow. Regarding dijit's focus policy, would it make sense to focus the drop down list when clicking on the arrow? This would comply with dijit's focus policy (something needs to be focused) and would also be intuitive for desktop and mobile users.

I think it makes sense to focus nothing.

The drop down list is by design not focusable. On desktop, focus is always on the <input>, even when pressing the down arrow key to "highlight" different items in the drop down list. The reason is so if the user suddenly starts typing letters or presses the TAB key, the right thing happens. So, focussing the drop down list would be quite difficult.

What would then happen, e.g., to a dialog containing a form with a FilteringSelect and being focussed upon opening? If I see it corretly, the FilteringSelect's textbox would be focussed and the keyboard would open, right?

Right, the textbox is supposed to be focused, which triggers the keyboard to popup, although that doesn't happen all the time (as explained by the link Paul posted above).

Hm… does it make sense to expect a different default focus behaviour on desktop and on mobile? In other words, focussing the FilteringSelect on a desktop platform would focus the textbox, and focussing the FilteringSelect on a mobile platform would (open and) focus the drop down list (explicitly touching on the textbox would focus the textbox and open the keyboard, of course)?

I'm not sure what behavior is optimal here. One question is how often the user will want to select something from the drop down list rather than typing something in.

We could certainly disable the Dialog's auto-focus behavior on mobile. Of course, the app can do that too by setting the autofocus parameter to false.

comment:23 Changed 7 years ago by Paul Christopher

Dialog's autofocus does not work with http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/themes/themeTester.html on my iPad since Mobile Safari seems to ignore this command. In the top menu bar, just click on "Dialogs", then "action bar". However if you run the very same page as web app, auto-focusing works on the iPad.

In my optimization for the iPad, I have always used Bill's approach: Setting dijit/Dialog's autofocus to false.

But maybe for other issue (like the above mentioned one with the arrow button), we need a patch of the core files?

comment:24 Changed 7 years ago by bill

Yes, that would be a big patch to the dijit code, and not part of this ticket.

comment:25 in reply to:  22 Changed 7 years ago by Alexander Kläser

Replying to bill:

I think it makes sense to focus nothing.

The drop down list is by design not focusable. On desktop, focus is always on the <input>, even when pressing the down arrow key to "highlight" different items in the drop down list. The reason is so if the user suddenly starts typing letters or presses the TAB key, the right thing happens. So, focussing the drop down list would be quite difficult.

Thanks for clarifying this, Bill. Then it was not the right idea and not focussing would be the only option.

Right, the textbox is supposed to be focused, which triggers the keyboard to popup, although that doesn't happen all the time (as explained by the link Paul posted above).

Ok, the following link also relates to that:

http://typeof.it/30/how-to-show-the-virtual-keyboard-using-javascript-in-ios/

There is also a nice example given there:

http://jsfiddle.net/DLV2F/87/

I'm not sure what behaviour is optimal here. One question is how often the user will want to select something from the drop down list rather than typing something in.

Hm… in the way we use it, FilteringSelect is rather a Select with an additional option to conveniently filter large lists via the keyboard. At least that is the way we use it. This is even more true on mobile device, I would say.

Do you see it rather as a drop down list or an text input field?

We could certainly disable the Dialog's auto-focus behavior on mobile. Of course, the app can do that too by setting the autofocus parameter to false.

Thanks a lot for the hint, I was not aware of the auto-focus behaviour. My guess would be that disabling auto-focus by default on mobile would be more intuitive, as focussing a widget intentionally seems to be more straightforward than finding out where and how to disable the auto-focus (at least that is my experience).

comment:26 Changed 7 years ago by Sebastien Brunot

The new version of dijit/Viewport and dijit/place has a few problems on iOS (tested with iPad 1 / iOS 5 and iPhone 4 / iOS 6), that can be seen using the dojo/mobile test page dojox/mobile/tests/test_Tooltip.html (see attached screenshot on iPad):

1) the soft keybord doesn't show up when a readonly input field has the focus, but Viewport ignore this fact. A simple patch is to change the focusin event handler for ios to have:

on(document, "focusin", function(evt){

if(!evt.target.readOnly){

focusedNode = evt.target;

}

});

I've attached a patch that does that.

2) for some reasons that need more investigation, place.around does not returns the best solution on iOS when the soft keyboard is displayed (for the "above" field, even with the soft keybord displayed, the best solution is still "above"...). To test this with dojo/mobile test page dojox/mobile/tests/test_Tooltip.html after applying the first patch, you can remove the readonly attribute on the input field labeled "above".

3) when the position is after, for the "above" input field, the tooltip is not correctly displayed (as in the original screenshot)...

Changed 7 years ago by Sebastien Brunot

Attachment: Tooltip-iPad1-iOS5.PNG added

Tooltip problem on iOS

comment:27 Changed 7 years ago by Sebastien Brunot

After trying to make sense of touch.around, I think I got it: when the keyboard is displayed on iOS, two things happens:

1) The height of the viewport is reduced according to the size of the keyboard;

2) The scrollX of the page is updated according to the size of the keyboard. My patch works with the (updated) test page dojox/mobile/tests/test_Tooltip.html, but the real scrollX update formula must be figured out (it depends somehow on the position of the focused field).

I've updated the viewport.patch accordingly, with a FIXME comment at the point where it should be updated with the current scrollX update formula.

Changed 7 years ago by Sebastien Brunot

Attachment: viewport.patch added

Fix viewport calculations on iOS (IBM CCLA).

comment:28 Changed 7 years ago by Sebastien Brunot

After discussing it with bill, I ran a few other tests, and it looks like dojo/windows.getBox is already returning the correct height of the document for an iphone 4 in portrait mode when the keyboard is displayed (it takes into account the keyboard height).

comment:29 Changed 7 years ago by Sebastien Brunot

same thing for the iphone 4 in landscape mode. I'm not sure to understand why there is a correction then... ?

Changed 7 years ago by Sebastien Brunot

Attachment: readOnlyFocusedNode.patch added

Do not adapt the height of the viewport on iOS if the focusedNode is read only (IBM CCLA).

comment:30 Changed 7 years ago by Sebastien Brunot

I've attached a new patch, readOnlyFocusNode.patch, to solve the first problem: the soft keybord doesn't show up when a readonly input field has the focus, but Viewport ignore this fact.

comment:31 Changed 7 years ago by bill

In [31193]:

Do not adjust the height of the viewport on iOS if the focusedNode is read only. Because readonly nodes don't cause the keyboard to popup. Thanks Sebastien Brunot (IBM CCLA). Refs #16730 !strict.

Git: 5ffd2525cb469847db35f2efcf34bcb16776ce09

Last edited 6 years ago by bill (previous) (diff)

comment:32 in reply to:  28 Changed 7 years ago by bill

Replying to sbrunot:

After discussing it with bill, I ran a few other tests, and it looks like dojo/windows.getBox is already returning the correct height of the document for an iphone 4 in portrait mode when the keyboard is displayed (it takes into account the keyboard height).

ISTM window.getBox().h includes the part of the document behind the keyboard. But, the document may end in the middle of the keyboard, or even at the very top of the keyboard, depending on where the scroll is. And of course when you focus a document and the keyboard pops up, the scroll changes.

Try loading any page in iPad or iPhone and dragging it up past the end of the document, so you can see the dark gray thatch behind the document. The document bounces back down as soon as you release your finger, *but* if you hold your finger in place, and simultaneously type dojo.window.getBox() in the console, you can see that height is a smaller number than usual.

I think that's what's happening sometimes when the keyboard is shown.

comment:33 Changed 7 years ago by bill

In [31208]:

Account for when viewport ends before the bottom of the screen, and thus keyboard is not obscuring as much of the viewport as we thought it was. Fixes #16989, refs #16730 !strict.

comment:34 Changed 7 years ago by cjolif

Cc: cjolif added

comment:35 Changed 7 years ago by bill

In [31324]:

avoid null pointer exception (regression from [31193]), refs #16730

comment:36 Changed 7 years ago by mtbvfr

Is there an Example page somewhere so that I can test this fix on my iPhone 3GS with iOS 6.1.3?

Thank you, Michael.

comment:38 Changed 6 years ago by Bill Keese <bill@…>

In ae10bd2ad5ae4718d0581d74cca9a89917c250ab/dijit:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:39 Changed 6 years ago by Bill Keese <bill@…>

In bf6d55e064408ee6738e772e67ad6d18969556d7/dijit:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:40 Changed 6 years ago by Bill Keese <bill@…>

In 0f7db0782c363fe5cbd0f62f21b6efa80e402477/dijit:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:41 Changed 6 years ago by Bill Keese <bill@…>

In 080cbc9a08b61ee44b105857f9bdf9cee85b28f8/dijit:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:42 Changed 6 years ago by bill

Milestone: 1.91.7.6

comment:43 Changed 6 years ago by Bill Keese <bill@…>

In 65b6085b6a8944147fba74238b19ce58ff6d616c/dijit:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:44 Changed 6 years ago by Bill Keese <bill@…>

In 20270e47fe6cbfa850d971c33c86b34e6f63068c/dijit:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 
Note: See TracTickets for help on using tickets.