Detect When Soft Keyboard is in Use abd Run a JS Function? - javascript

I have a site that opens a modal upon click that contains a form. I noticed on my iPad that when the soft keyboard is open it covers several fields of the form, and as I am near the bottom of the screen, I cannot scroll to reveal those hidden fields.
In researching this issue I came across this answer which includes code from this answer. However, neither of these answers seem to work when tested on iOS 8.3.
Here is what I would like to achieve:
Detect when the keyboard is opened.
Find the height of the keyboard.
Add padding to the bottom of the footer to accommodate the height of the keyboard.
When the keyboard is dismissed or closed, the padding is removed.
There are a few things to note:
If someone is using a connected keyboard (including bluetooth keyboards) don't do anything as the soft keyboard shouldn't appear
jQuery is okay to use.
A solution must run via client side code.
I prefer a solution that covers iOS and Android. Preferably, any device that can use a soft keyboard.
How could I achieve a solution that will increase the padding in my footer, that will work on the majority of devices, when someone is using a soft keyboard as a means of filling out a form in a modal?

I bumped into a problem similar to this not too long ago and I found a small solution to this, when a mobile or tablet is being used and a keyboard is activated it triggers a resize event of the screen so you could use that to trigger a function.
var lastHeight = $(window).height(); // store the intial height.
var lastWidth = $(window).width(); // store the intial width.
var keyboardIsOn = false;
$(window).resize(function () {
if ($("input").is(":focus")) {
keyboardIsOn =
((lastWidth == $(window).width()) && (lastHeight > $(window).height()));
}
if(keyboardIsOn){
var keyboardHeight = lastHeight - $(window).height();
$("footer").css("padding", keyboardHeight+"px");
} else{
$("footer").removeAttr("style");
//or if you just want to remove the padding
//$("footer").css("padding", 0);
}
});
//An alternative solution is by checking if the height of the screen
//change on input/textarea focus.
$('input, textarea').focus(function() {
keyboardIsOn =
((lastWidth == $(window).width()) && (lastHeight > $(window).height()));
if(keyboardIsOn){
var keyboardHeight = lastHeight - $(window).height();
$("footer").css("padding", keyboardHeight+"px");
} else{
$("footer").removeAttr("style");
//or if you just want to remove the padding
//$("footer").css("padding", 0);
}
});

Related

jQuery's scrollTop() behaving strange on Android browsers including Chrome

I'm having trouble with an animated scrollbar. The intended behaviour should be on clicking the nav-button, scroll with ease to the end of the page(and a little break near the end).
Now the problem on PC works perfect. On android device (I tried my phone), the scrollTop value and the ($(document.body).height() - $(window).height()) do not match. There is exactly 55px less with the scrollTop thus acting all sorts of strange... Also sometimes it works sometimes it doesn't. I've figured it has something to do with the browser bar collapsing and upsetting the value...but i can't figure it out.
I've tried the following: initializing the variables on scroll event, i've tried vanilla js that didn't work. Need help :) for reference http://www.developer.morningmood.org , also i've printed out the values on bottom of the page if it helps. Here's the code.
contactF = Math.floor($(document.body).height() - $(window).height());
$("#cont").click(function(){
if ($(document).scrollTop() < contactF && flagScroll==true){ //flag stops other buttons from beying pushed
flagScroll = false;
var inter = setInterval(function(){
var doc = $(document).scrollTop();
if (doc == contactF){ // this is the final desired position
clearInterval(inter);
flagScroll = true;
pix = 10; //pixels to jump
return;
}
if (doc >= contactF-50){ // this is a break on aproach
pix = 1;
}
$(document).scrollTop(doc + pix);
}, 10);
}
})
EDIT: also to find the bug, you nedd to scroll from the top of the page all the way to the bottom, if from the top of the page you just push the contact button it works. but if you scroll it doesn't, it upsets the value...
Had the same exact problem and spent a whole day to figure it out.
You are right about the address bar collapse on Android chrome messing it up. Turns out the jQuery function $(window).height() always reports the viewport height that is before the address bar collapses. To get the correct value, use window.innerHeight instead. You can find more information about URL bar resizing here https://developers.google.com/web/updates/2016/12/url-bar-resizing
You can also find people asking similar questions regarding the safari address bar auto-hide, the solutions are similar. Mobile Safari $(window).height() URL bar discrepancy

sticky navbar does not work on mobile while scrolling

I've created a sticky navbar for a subnav, which should stick at the top of the screen when the user scrolls down. Therefore I've tried some javascript, which changes the position to 'fixed' when the top is reached. Avoiding a gap in the content when the navbar is taken out of the flow, I've also added a placeholder, which has the same height as the navbar.
On Desktop it really works and looks how it should be. But I got a "touch" issue on mobile view. When I scroll down on mobile view the navbar will not appear during the process of scrolling over the viewpoint, where the css class is changing. It only appears when I stop scrolling after that viewpoint. When it shows up I can normally scroll up and down and I am only getting this issue again if I repeat this procedure, where the navbar has to change the css class. So it might be a problem with the css class change and I guess the problem could be in the javascript snippet. Does anybody know a solution for this? I'd like to have the same behavior like on desktop view, so the navbar is always visible and just fixed to the very top of the screen, even if it is in the flow of scrolling.
JS:
var menu = document.querySelector('#irp-localnav');
var menuPosition = menu.getBoundingClientRect();
var placeholder = document.createElement('div');
placeholder.style.width = menuPosition.width + 'px';
placeholder.style.height = menuPosition.height + 'px';
var isAdded = false;
window.addEventListener('scroll', function() {
if (window.pageYOffset >= menuPosition.top && !isAdded) {
menu.classList.add('sticky');
menu.parentNode.insertBefore(placeholder, menu);
isAdded = true;
} else if (window.pageYOffset < menuPosition.top && isAdded) {
menu.classList.remove('sticky');
menu.parentNode.removeChild(placeholder);
isAdded = false;
}
});
If you guess an error in the html/css markup, just let me know, so I get in touch with you again by posting this markup
Kind Regards
I was able to hack around. For anyone, who is facing a similiar issue:
Mobile browsers simply do not fire on a scroll event, while the event is in process. They fire when the event has stopped, so, when you've stopped scrolling. Using translate3d(0px,0px,0px) can solve this. Refer to this thread to read more about it:
iOS 9 Safari: changing an element to fixed position while scrolling won't paint until scroll stops
Kind Regards!

Is there a reliable way to detect scrolling, on all devices, using javascript/jQuery?

I've been struggling with this for a while, and I'm surprised that doing this isn't more straightforward...
I need to detect when the user scrolls a page, either with the mouse, scrollbar or by touch on mobile devices. jQuery has their scroll() function which works alright, but it requires that the page is actually scrolling. I want to detect the scrolling wether the page is scrolling or not (say I reach the end of the page, and there is nowhere left to scroll too.. I still want to know if the user is trying to scroll)
I found another question that had asked something similar, along the lines of detecting scroll input even when the page isn't scrolling, and I got this chunk of code:
if (document.addEventListener) {
document.addEventListener("mousewheel", MouseWheelHandler(), false);
document.addEventListener("DOMMouseScroll", MouseWheelHandler(), false);
} else {
sq.attachEvent("onmousewheel", MouseWheelHandler());
}
function MouseWheelHandler() {
return function (e) {
var e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if (delta < 0) {
// increase scroll amount
} else {
// decrease scroll amount
}
}
return false;
}
At first, this seemed to do the trick, but I'm finding it doesn't really return balanced results with different types of mice, and didn't work too smoothly with touch events, which is the core aspect of this question.
I'm using this in a project that does a lot of fancy events on scroll, with the actual page not actually scrolling at all... But I'm running into the problem of it being incredibly slow with all my standard mice, but incredibly fast on my Apple Magic Mouse. I know that there will naturally be some difference here, as the magic mice do scroll quicker, but the difference is far more off balance than it is between the mice normally.
I'm hoping there is a way to improve upon this to get a more reliable result, with all sorts of different inputs. Any suggestions?
Edit:
To clarify, in order for an answer to work for me, it needs to work on an element which is not scrollable. I have a page which does not scroll at all, but which has other events that fire when the user scrolls. This means that I cannot use properties that are based on the window's scroll position (such as scrollTop()).
You should use window.onscroll most usage and then create a new listener to deal specifically with top and bottom scroll conditions I would suggest using a mousewheel event for desktop browsers and a specifically coded touch responder like below to detect if they are trying to scroll, what direction and if that is possible at the current window.scrollY value.
var isOverScroll = function isOverScroll ( touchStartY, touchEndY ) {
if ( Math.abs( touchStartY - touchEndY ) < 5 ) &&
( ( window.scrollY = window.innerHeight && touchStartY - touchEndY > 0 ) ||
( window.scrollY = 0 && touchStartY - touchEndY < 0 ) ) ) {
return false;
}
return true;
}
There is no way to detect scrollbar events, combine this with your current code and only trigger mouse wheel and touch events if the scrollY position is at either 0 or max.
On a side note if you are trying to get rid of the scroll bar completely that is a very bad idea as it is both a wonderful tool for users as well as something that is a standard part of the ui. If you trying to do a scrollable fullpage app and don't want a scroll bar try using slides. Either way don't continue setting the scroll value thats slow instead just move the whole body using css:
transition: transform3d( 0, YOURSCROLLVALUE , 0);
One possible solution is using a plugin for scrolling like
ISCROLL
in this example here :
Example
they use the feature pull to refresh , which will fire upon reaching the maximum scroll available , here by you can use any custom function (even if your item is not scrollable ).

jQuery solution to detect for touch only device?

I have designed my site with an image gallery that does not display the next / previous arrows until the mouse is rolled over them .next:hover{display: block} This is fine but the site is fluid and I did not think at all that hover (mouse over) does not work on touch screen! I do not want to keep the arrows on constant display unless the device is touch screen only like an ipad for example!
What is the best way to detect if the device is touch only and if so change display: none to display block automatically. Is there a jQuery way of doing this?
I hope this makes sense, I have googled it and search on S.O. but am unable to find a direct answer. That along with the fact that I am a bit (understatement) of a novice when it comes to jQuery!
Thank you for any help
I worked something out like this, the click counter also fires on touch events when I was testing it.
// Detect touchscreen only
var touchscreenonly = true;
var moves = 0;
var clicks = 0;
$("body").mousemove(function() {
moves++;
if (moves > clicks + 1){
touchscreenonly = false;
// now unbind these functions if you like
$(this).unbind("mousemove").unbind("click");
console.log('mouse moved, this is not a touch-only device');
}
}).click(function(){
clicks++;
});
I was in a same situation like you but, I did not wanted to use Modernizr, so as a quick fix I just checked for the window width.Most of the touch devices including tablets falls below the width of <=1024. So I wrote the below piece of code inside document.ready:
$(document).on("ready", function() {
if ( $(window).width() < 1025 ){
//Insert your code to add/display something different for mobile/tablet devices
}
});
Hope it helps someone.

Switch tabs based on mouse scroll

I would like to have a widget on a webpage containing a number of tabs. When the user scrolls the page and the widget comes in to view and he keeps scrolling down, the tabs should be activated one by one (without the page scrolling further down). Once the last tab is showing, the page should resume scrolling as usual. Is this doable using JS/jQuery?
UPDATE:
Since this seems too broad a question:
The problem is, I don't know how to use the scroll offset and prevent the page from scrolling down until I decide it can resume its normal behavior
UPDATE 2
I created This fiddle,
$(document).ready(function(){
$('#tabbed').mouseover(function(){
$(this).focus();
}).scroll(function(){
console.log("scrolling tabs");
});
$(window).scroll(function(evt){
var scrollPos = $(this).scrollTop()
console.log(scrollPos);
// BULLETPROOF WAY TO DETECT IF THE MOUSE IS OVER THE
// SCROLLABLE DIV AND GIVE IT FOCUS HERE?
});
});
it contains a long page and a scrollable div among its contents. The only problem is that the div starts catching scroll events only if I move my mouse. If I could find a bulletproof way to activate the scrolling div whenever the mouse is over it I'm there. Any ideas?
You can't prevent scrolling with javascript. Using iframes and divs with scroll will only work if the mouse is over them.
You can cancel the mouse wheel and keys events related to the scrolling, however the user will be able to scroll using the scrollbar (more here).
Another approach is leaving an empty area and fixing your widget inside this area, like in this working example
$(window).bind('scroll', function()
{
var scroll = $(window).scrollTop(),
innerHeight = window.innerHeight || $(window).height(),
fooScroll = $('#fooScroll'),
emptyArea = $('#emptyArea'),
offset = emptyArea.offset(),
fixedClass = 'fixed';
if(scroll > offset.top)
{
if(scroll < offset.top + emptyArea.height() - fooScroll.height())
{
fooScroll.addClass(fixedClass);
fooScroll.css("top", 0);
}
else
{
fooScroll.removeClass(fixedClass);
fooScroll.css("top", emptyArea.height() - fooScroll.height());
}
}
else
{
fooScroll.removeClass(fixedClass);
fooScroll.css("top", 0);
}
});
Then you can change the tabs while the page is scrolling.
You should be able to do this. You can use the jQuery scroll event to run your own code whenever the user scrolls up or down. Also, so long as you call e.preventDefault() whenever the scroll event is fired, you can prevent the whole window from scrolling up or down.

Categories