resize versus orientationchange

Feel my pain:

// On Android, "resize" fires on orientation change, but ALSO every time
// the on-screen keyboard pops up. (iOS does not do this.)
// And changing the document layout hides the Android keyboard again!
// So on Android, we must use the "orientationchange" event instead.
// But iOS does not fire "orientationchange"! FFFFFFuuuuuuuuu....!!!!
if (navigator.userAgent.match (/Android/i)) {
Is this an Android thing or a Chrome thing? Do I need to match
 // on other Android browsers? Who fucking knows.
 // Oh, also the window isn't resized yet when this pigfucker fires.
 // Is half a second enough time? Who fucking knows.
 window.addEventListener ("orientationchange",
   function() { setTimeout (dnairc_resize, 500); });
} else {
 window.addEventListener ("resize", dnairc_resize);

Anyway, please go watch my webcast on your weird-assed phone and tell me whether it fucks up in some new and exciting way.

Update: To be clear, the way it's trying to lay things out is:

  • Portrait: Video is full width; chat is below it.
    • But if that chat would be below a minimum height, it is omitted and you get video only.
  • Landscape: Video on the left, chat on the right.
    • But if that chat would take up more than 50% of the screen, it is omitted and video goes full-width.

This means that on particularly small screens, you might get video-and-chat in portrait and video-only in landscape.

This Android nonsense of resizing the window when the keyboard is exposed means that it switches between portrait and landscape when the keyboard pops up, so everything tried to re-flow, and somehow that caused the keyboard to disappear again.

Previously I had attempted to do all of this with CSS media selectors instead of computing all of the sizes in Javascript, but that was even more of a nightmare.

Previously, previously, previously.

Tags: , , , ,

14 Responses:

  1. Andrew Klossner says:

    I can't get the on-screen keyboard to appear at all when I touch the box to the right of Name (prompt "Type your name first").

    On a Pixel 1 (5-inch screen, Android 10), rotating to landscape changes orientation and I don't see the schedule and Name box. That probably makes sense for this amount of screen. On a Huawei MediaPad M5 (8-inch screen, Android 9), rotating to landscape puts the video and schedule side by side, but touching the input box still doesn't bring up a keyboard.

    These are both running Firefox 68 (the old one, I'm not keen on adopting the new one).

    • jwz says:

      That's because you ... didn't type your name first.

      • Andrew Klossner says:

        Ah, you're right. I took "Name" as a label and "Type your name first" as the prompt in the entry box.
        The keyboard does in fact work as expected.

  2. I don't have advice for you but I sympathise. Phone browsers really screwed up resize/keyboard/orientation events (in different, unique ways) and dealing with it is a massive pain in the hindquarters.

    • Jim says:

      browsers really screwed up ... in different, unique ways

      FTFY. Polyfill is my favorite word for massive kludge.

  3. Billy says:

    Android 9 with Opera:
    - looks good in both portrait and landscape; the text entry fields are not visible in landscape;
    - touching Name in portrait brings up the keyboard, which obscures the text entry fields; this happens often and is not limited to just your site;
    - opening the keyboard in portrait and then rotating to landscape shrinks the video (tried this twice - different sizes each time), and the keyboard vanishes and is replaced by black; not sure I've seen that before but I'm also not sure I've carried out those actions before.

    I have screen caps if they're any help.

  4. CdrJameson says:

    'Resize' on Android has to fire when the OS keyboard comes up, because - fun fact, Android developers - there is no programmatic way to find out that the OS keyboard is up or not. All you can do is see that your visible area just shrank by a roughly keyboard-sized chunk.

    And good luck navigating that keyboard if you're using a game controller...

    • jwz says:

      "Has to". For surely there could be no other way to impart this information.

      • CdrJameson says:

        I'm sure there must be a very sophisticated technical reason why the obvious way isn't available. Either that or Android is just a quick, hacked together job. It couldn't possibly be that though.

        • says:

          Well, unless convinced otherwise, I'd assume that it's simply not a web page's business whether the keyboard is on screen or not.

          Is there really no way to a) react to the new visible area without regard to the reason it changed and b) do it in a way that does not cause the input field to lose focus or be removed temporarily, which is presumably the reason why the keyboard disappears?

  5. Kyzer says:

    Yes, I feel your pain.

    // Hooray, "console.log.apply(this, arguments)" is not portable.
    if (arguments.length == 1) console.log(arguments[0]);
    else if (arguments.length == 2) console.log(arguments[0], arguments[1]);
    else if (arguments.length == 3) console.log(arguments[0], arguments[1],
    else console.log(arguments[0], arguments[1], arguments[2], arguments[3]);

    Did you want, console, arguments) ?

    • jwz says:

      If I had reason to believe that was portable, sure?

      • Kyzer says:

        Nothing about console in browsers is standardized (yet), so all code referencing it is equally non-portable. The specific invocation you call "not portable" is, as far as I know, portable to all browsers except Internet Explorer 8-10. Microsoft fixed it in IE 11. You wrote special-case code to deliberately support Internet Explorer.

        If you had problems with it on other browsers, it'd likely be a consequence of writing console.log.apply(this, ...) instead of console.log.apply(console, ...)

        If you want a single incantation that works on all browsers but doesn't log on IE≤10, write:
        if (console && console.log && console.log.apply) console.log.apply(console, arguments)

        If you want to also want it to log on IE≤10, write:
        if (console && console.log), console, arguments)

  • Previously