Projects‎ > ‎UI‎ > ‎

Mobile and tablet support

Scrollbars and zooming

Problem and solution

The client-side code creates a few overlays (error dialog, loading indicator, message), which don't contain any XForms markup that relies on the container being rendered on the page to initialize properly. We want those overlays to be really hidden so they don't constrain how wide or high our browser needs to be. We want to:
  1. Avoid the presence of unnecessary scrollbars on desktop browsers—granted, a minor inconvenience.
  2. More importantly, make it so mobile devices (e.g. iOS) don't believe that the page is larger than it really is, and don't show the content "zoomed out" with the actual form extremely small at the top left of the screen.
We avoid this problem by making those overlays really hidden, setting the display: none on beforeHideEvent, and setting display: block on beforeShowEvent.

Avoiding scroll when showing a message

A consequence of the above solution is that when running xforms:message, the page scrolls up. This is happening because the Panel code registers a listener on show and runs focusFirst, which sets the focus on the first focusable control in the form.

The center method is registered on the beforeShowEvent, and is supposed to move the dialog to the center of the viewport before the focus happens. But center is unable to do this, since it is running on beforeShowEvent, and at that time, the overlay is not visible yet. It tries to reposition the overlay using Y.Dom.setY(), which has no effect, as Dom._setXY() doesn't do anything when Dom._getXY(node) returns false, as Dom._canPosition returns false when the element is display: none.

The element is display: none because we set it so in overlayUseDisplayHidden, as described above. There, on beforeShowEvent, we remove the display: none. But our listener on beforeShowEvent runs after the one for center, so when center runs, it it is display: none.

To fix this issue, we want our listener to run before the center listener. So, instead of calling subscribe which adds the listener at the end of the queue, we call beforeShowEvent.subscribers.unshift(…). This way, our listener that set display: block runs before the center listener.