I'm building an Angularjs app that has a at the bottom of one view.
Problem in mobile safari on iOS9:
When focusing the textarea the soft keyboard is shown and covers the lower part of the view.
How can I scroll the page up when the keyboard is visible so that the content (i.e. the textarea) is not covered?
Here is one way you might prevent scrolling. Add overflow:hidden to the document body when your inputs are in focus.
function toArray (collection) {
return Array.prototype.slice.call(collection);
}
function noScroll (event) {
if (event.type === 'focus') {
document.body.classList.add('no-scroll');
}
else if (event.type === 'blur') {
document.body.classList.remove('no-scroll');
}
}
var inputs = toArray(document.querySelectorAll('input'));
inputs.forEach(function(input){
input.addEventListener('focus',noScroll,false);
input.addEventListener('blur',noScroll,false);
});
.no-scroll {
overflow:hidden;
}
To scroll the page up, you could use document.body.scrollTop when the inputs are in focus and set the value to the desired location.
Related
I have a simple HTML form where the input elements (text boxes) are centered on the page. Problem is on mobile devices (specifically Android) when the keyboard comes up, it covers some of these elements. Even when I tap next while filling out the form, the page doesn't scroll to reveal the hidden elements. Any suggestions? Is there some JavaScript or CSS that I can add?
Try using onfocus javascript event. If You use JQuery, you can use this sample, which, if device is touch screen device, scrolls input to very top of viewport on every input focus event.
function isTouchDevice() {
try {
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
}
$("input").focus(function(){
if( isTouchDevice() ){
$('html, body').animate({
scrollTop: $(this).offset().top
}, 1000);
}
})
I have some textarea elements where a user can enter a message to a companion.
These are presented in a modal in the Phonegap WebView.
When the modal is present on screen I disable the scrolling on the WebView body like so:
document.ontouchmove = function(e) {
e.preventDefault();
};
Likewise when I hide the modal I re-enable it like so:
document.ontouchmove = function(e) {
return true;
};
The textarea elements do not seem to be able to scroll on touch events. I looked into this and tried applying the following CSS:
overflow-y: scroll; /* has to be scroll, not auto */
-webkit-overflow-scrolling: touch;
But this did not help.
When the user enters some long text the textarea moves in line with the amount of text but a user cannot scroll back to a previous position.
Is there a solution to this?
You could just look to see if the move event was coming from a textarea and allow those events to pass through.
document.ontouchmove = function(e){
if(e.srcElement.type !== "textarea"){
e.preventDefault();
}
};
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.3/jquery.mobile-1.4.3.min.js"></script>
Add jquery Mobile js in head tag .. it will work
As you tab between input fields in a browser, the browser will automatically scroll the nearest parent container to place the next focused field within the view.
Simple JSFiddle: http://jsfiddle.net/TrueBlueAussie/pxyXZ/1/
$('.section').eq(6).find('input').focus();
For example if you open the above fiddle it selects "Sample item 7" at the bottom of the yellow window. If you press tab the "Sample text 8" field jumps up towards the middle of the parent window.
Obviously this is a great thing for normal websites, but I have a custom scrolling container in which I position & scroll everything manually. I am tracking focus changes and will use a momentum scroller to bring it into view, but how do I disable the default scrolling behavior of web-browsers? Happy to accept CSS, Javascript or JQuery solutions.
This is just winging it based on my comment above:
$('input').on('keyup',function(e){
if(e.keyCode === 9) {
var $this = $(this);
// (do your scroll thing here
// ..., function(){
$this.parent().next().find('input').focus();
// });
}
});
Long as the callback timing is correct, this will only change focus after you have already scrolled. You'll need to do your own magic to determine what to scroll to, but this should give you the focus behavior you want.
Turns out you can't smooth scroll for focus changes as the events happen in the wrong order. You get an awful delay while it scrolls the field into view, before focus is set. A better move of the item onscreen, or superfast scroll, is all we can hope for.
As suggested by PlantTheIdea (+1'ed), you need to catch the TAB key and find the next focusable item, bring it into view, then set focus to it.
In practice there are a number of issues to resolve:
Change of focus occurs on TAB keydown (not keyup).
Only match non-hidden inputs (lots of web apps have hidden fields that will go bang if you try to focus them).
Allow for the selection to tab off the first or last item on the page (otherwise the browser loses the ability to tab to its address bar)
use e.keyCode || e.which to allow for older browsers
catch event at document level to allow for cases of other inputs, outside of the scrolling area, causing it to enter the scrolling area (first or last input).
The final code looks like this:
$(document).on('keydown', ':focus', function (event)
{
if ((event.keyCode || event.which) == 9)
{
var $inputs = $(":input:not(hidden)")
var index = $inputs.index(this);
// Index previous or next input based on the shift key
index += event.shiftKey ? -1 : 1;
// If we are in the range of valid inputs (else browser takes focus)
if (index >= 0 && index < $inputs.length)
{
var $next = $inputs.eq(index);
event.preventDefault();
// Move, not scroll, to the next/prev item....
MoveIntoView($next);
$next.focus();
return false;
}
}
});
I have a lot of small windows on my site and my script close them when user clicks on the background
$(document).mouseup(function (e)
{
var container = $("#"+active);
if (!container.is(e.target) && container.has(e.target).length === 0) {
$('#'+active).fadeOut(200);
}
});
The problem is they also hide when the user scrolls the site - how can I detect that the user is not just clicking the scroll bar?
You can bind the event specifically on body instead of only on document:
$(document.body).mouseup ...
I'm making a webpage for iOS. I would like to perform an action when the user scrolls to the very top of the page via tapping the status bar (a shortcut). I don't want to perform this action when the page is scrolled to the top via using finger swipes.
So far, I have this code, which will wrongfully get triggered in both cases:
Event.observe(
window,
"scroll",
function(event) {
if (window.scrollY <= 0) {
alert("You are at the top of the page, but I don't know how you got here");
}
}
);
Since this code is triggered after tap event, you can set a flag on that tap event which you can check later in this scroll event capture
Event.observe(
window,
"scroll",
function(event) {
if ( !flag )
{
if (window.scrollY <= 0) {
alert("You are at the top of the page, but I don't know how you got here");
}
}
flag = false;
}
);
This flag is set when you tap on that status bar