Durandal provides a modal dialog facility which works great on desktop devices, and it allows you to control the presentation of the dialog via the "dialog context".
The default dialog context will, among other things, "display your dialog's view centered on the screen." Observationally, I can see that this means centering the dialog in the viewport--which means that as you scroll up and down, it remains in the same location, in the middle of your viewport.
This works fine a screen large enough to see the entire dialog; but on mobile devices, particularly phones, the dialog may be larger than the screen, especially if the user zooms in. When this happens, it is impossible for the user to pan around the dialog.
I would like to change this behavior by using a custom dialog context that positions the dialog in the center of the viewport initially, but then leaves it anchored to a fixed spot on the page, so the user can pan around.
So far I have been unable to figure out how to setup a custom dialog that observes the regular Durandal defaults, except for the "center in the viewport" rule. I'm not even positive I want or need to do this as a custom context; there may be a CSS rule that will accomplish this? Any help would be greatly appreciated.
As suggested by Abhinav Gauniyal and PW Kad (thank you!), a CSS solution turned out to be much simpler than a custom context.
After some digging, I found that by changing position: fixed to position: absolute in durandal.css, on the .modalHost rule, I was able to get the behavior I was looking for.
Better would be a completely separate UX for mobile devices that was tailored to their screen size, and that's definitely the direction we want to head--but today I wanted to at least make it possible for existing users to pan around and see the entire modal dialog, instead of leaving them with something completely unusable until we've got a "complete" mobile UX in place.
Related
I have been searching for the best part of a day in order to try and find a way around this but cant. So here I am.
Basically I am working on a component which is position: fixed; to the bottom of the mobile browser's viewport window. This is trivial in itself.
The issue is that the company's native iOS app has an Apple association file which presents the Apple smart banner to open the native app at the top of the page.
When this is presented to the end user it seems that the browser redefines what it classes as the bottom of the page and, as a result, anything which is fixed to the bottom of the page is overlapped by the navigation toolbar which appears.
The only solution I can think of is to write out a list of all Apple mobile device viewport sizes and then compare the size of the window.innerHeight value on the onresize event -- which seems like absolute overkill and still has some nuance in itself.
I have added some screen shots to illustrate the problem and what I would like to achieve.
Thank you in advance to anyone who can assist with this. I have searched through the answers to other questions but they all seem to be people either trying to surface a smart banner or people trying to redirect to their app.
I have managed to find a solution by leveraging the resize event in the document window and then setting the top attribute of the element to window.innerHeight - element.clientHeight.
If there is a better, more performant way of achieving this I would love to still hear the answer but I will, for all intents and purposes, mark this as answered.
On a side note this does feel like a bug in the Safari browser itself as it seems that Apple are altering what they consider to be the bottom of the document.
Solution:
window.onresize = () => {
const button = document.querySelector(".add-to-bag--sticky");
if (button) {
button.style.top = `${window.innerHeight - button.clientHeight}px`;
}
};
IE has a interesting fullscreen mode. I still don't understand it very well but I have observed two cases:
The menu bar and additional attached toolbars hide (slide up) and it is a real real fullscreen experience. This is kind of nice.
The window frame (chrome) disappears but the menu bar and other bars still remain. They float and hide the page content partiallly.
I have looked at some pages and they basically don't deal with it. Stackoverflow.com is an example of this. The black top toolbar is hidden and the scrollbar is hidden partially too. I cannot know whether I am logged in or not (or how many reputation I have). This is problematic since I have various buttons near the top corner and when in fullscreen mode the user is not able to click on them.
Should I try to deal with it? If so how? (I would need to know how many pixels the toolbar takes to move my button accordingly. It varies since people are can attach as many as toolbars as they want)
Any help is highly appreciated.
I have upgraded from version 11.0.9600.17420 to 11.0.9600.18204 and it works consistently now. The page is only hidden when the mouse is near the top :)
On iOS devices, scrolling plugins like Scrollify.js, FullPage.js, and OnePage-Scroll.js seem to keep Safari's address and navigation bars in place, instead of the way they typically minimize when the user scrolls the page.
Is there any kind of workaround for this? I understand that when those UI bars minimize, the inner viewport height is changed, and so the plugin would need to recalculate the height. Also, the UI minimizes during the scroll event, and maybe that's problematic for the scrolling plugin? Is there a way to maybe hide the UI when the scroll event finishes?
When you change the orientation of the iPhone from portrait to landscape, the bars disappear, but if you bring them back by tapping the top or bottom, they stay put when you scroll.
I'd really like to have that extra height!
Is there any kind of workaround for this?
You can also use it without autoscrolling, but that might no be what you are looking for: autoScrolling:false.
If you are worried for the landscape mode, if you avoid using anchors and you load the page in portrait mode to then change to landscape, it won't show the top bar at all on iOS at least. Not the best solution, but it might help.
Personally I would recommend you to use the option responsiveWidth or responsiveHeight to change the behavior of the page on small screen devices and remove the auto scrolling and possibly have bigger sections.
In general, mobile browsers do not allow access to the top or bottom bars behaviors and there's no much developers can use to deal with them.
I'd like to detect in some "nice" way (Modernizr most likely, but whatever) whether a layout should have embedded scrollable regions of the page, or else (for some mobile use) should just flow all content as one scrollable mass.
The specific case is a "EULA"-like page, where there's a form with an "I ACCEPT" button or whatever, and then a mass of hideous all-caps legal stuff. On a big screen I'd like the whole form visible, so I'd like to put the legal stuff in its own scrolling box. However, on a mobile device that would be kind-of ugly (though I'm no mobile ux expert), so I was thinking of just dropping it all in-line so that the user could read the text (LOL) with simple swipes to scroll, and then at the bottom the buttons would scroll into view.
I suppose I could just check for touch with Modernizr, but that doesn't seem quite right.
edit — though I'm pretty sure that what I described would probably be a usability win anyway, the thing is I'm finding that my Android devices won't pay any attention to "overflow: auto" on a <div> in the middle of a page.
The approach I've taken is to rely on Modernizr.touch and Modernizr.overflowscrolling tests. If Modernizr inserts the touch and no-overflowscrolling classes in the html element in the DOM (or just check Modernizr.touch and Modernizr.overflowscrolling directly), then I avoid overflow:auto. This means that Android devices that mishandle overflow:auto do not get it.
This might be an imperfect solution; there might be devices that can handle overflow:auto that don't get it in this case. But that's not exactly the end of the world, at least in my case. And it seems to work correctly for all the most common devices/browsers.
And it has the virtue of being simple. I already had Modernizr loaded for other uses.
As others have said, the Modernizr.overflowscrolling checks for the overflow-scrolling css property, not for whether the device can scroll content within a div using overflow: auto.
In fact, in my recent testing, the Nexus 5 actually returns Modernizr.overflowscrolling as false, so it cannot be relied on.
This very small script (with no dependencies) seems to enable touch scrolling for devices (Android 2.3) lacking support...
http://chris-barr.com/2010/05/scrolling_a_overflowauto_element_on_a_touch_screen_device/
Link to repo:
https://github.com/chrismbarr/TouchScroll
I have a full-screen game in HTML+JavaScript, which uses the arrow keys as primary controls. This cannot be used on keyboardless Android devices (I haven't tested on iOS), and even if the soft keyboard had arrow keys it would take up unnecessary space. Therefore, I have added onscreen control buttons. However, the buttons are unnecessary (and absurdly large) on desktop browsers, so I would like them to not pop up unless they are needed.
What heuristics can I use to decide whether they are needed — that is, whether it is impossible or awkward for the user to input arrow-key events — other than recognizing specific User-Agents (which is straightforward, but not future-proof)?
I will of course allow the user to hide/show the buttons; I am looking for useful heuristics for choosing the default setting.
No need for any user-agent sniffing, config options or any kind of guessing. Just do this:
Have a title screen which says "press to continue".
On click or key press, hide touch controls and start game.
On touch, show touch controls and start game.
You never even needed to mention the option to the user and you auto-detected their preferred control perfectly.
Use feature detection with Modernizr: http://www.modernizr.com/docs/#touch
While this is not a reliable way to check if the user has a keyboard it is definitely reliable to see if the browser is capable of touch.
Instead of trying to guess, make it a config option for the user to choose.
If you have only arrows (left/right/up/down) you might consider adding touch-events inside the game field? This would not take up space obviously as it is layered on top of the game, so it could be 'always on'.
A computer user would not even know it is there, though he/she could use them to play your game with a mouse I guess.
The touch-device user on the other hand can much more easily use the "areas" (mid top, mid left, mid bottom and mid right for instance) because of .. well.. touching instead of using a mouse.
This might need some explaining, as you probably would not want the points to be visible to the user, but it feels like a valid option.
Even if you have 4 buttons and a 'fire', you could do this, for instance by adding a 'middle' section.
look for touch specific events such as touchstart or gesturestart and show the onscreen controls if detected.
http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
I am not sure if the system-info api has been implemented by any browsers:
http://www.w3.org/TR/system-info-api/
rather than displaying the on-screen keyboard by default, add a button to toggle the display of the on-screen keyboard.
It might also be prudent to give the on-screen keyboard the ability to be resized.
Edit to answer question:
Keyboard should be hidden by default if most of your users are going to be on a computer,
Visible by default if most of your users are going to be on a mobile device.
You can consider checking the display size. If the display size is smaller than a certain size, you can assume that it is a mobile device and can display the Arrow Buttons. Other wise use keyboard buttons.
You can also keep an option so that user can set this manually if needed.
You could use javascript to find out the height of the windows view port and then us an if statement saying:
if ($(window).height() <= "960")) {
//Your code to display keyboard controls
//P.S. 960 is height of iPhone 4+ screen
}
Edit: Left out ) at end of $(window).height() <= "960"