Google's autocomplete not activated by pasting with mouse - autocomplete

The Google autocomplete API doesn't seem to be activating by pasting content into a text input with the mouse. It works fine if involving the keyboard at all, but not with just mouse.
I did notice, however, that after you paste your content into the text input it will activate from almost any keypress (tested right arrow key, end key, space).
You can repro it here on their autocomplete demo site.
Is this a bug? or as designed? If it's as designed, how to apply workaround?
I've got this as a workaround so far, but no simulated keypress events seem to work.
$('.txtLocation').bind("paste", function (e)
{
$('.txtLocation').focus();
var e = jQuery.Event("keydown");
e.keyCode = 39; //39=Arrow Right
$('.txtLocation').trigger(e);
});

It seems this impacts not only the context-menu Paste, but also that of Edit|Paste from the browser menu bar as well as the iOS paste functionality. I've opened a bug with Google. You may wish to "Star" that bug report to catch updates.
I found a workaround that, while a bit of a hack, seems to fix the problem. If you store the pasted value, switch focus on a different field, set the value in the Autocomplete field, and finally focus back on the Autocomplete field things work more or less as expected. Also, you have to do this in a setTimeout() callback - the delay time doesn't seem to matter at all, but if you just do this inline you won't see the expected results.
Here's a code sample of what I'm describing above:
$("#address_field").on("paste", googleMapsAutocompletePasteBugFix);
googleMapsAutocompletePasteBugFix = function() {
return setTimeout(function() {
var field, val;
field = $("#address_field");
val = field.val();
$("#price").focus();
field.val(val);
return field.focus();
}, 1);
};
The last focus() is optional, but the UI is a little less surprising than if you just skipped automatically to the next field.

Following solution seems to work for me (existence of field ending with "address_2" is assumed). Tested on IE8, IE9, IE10, Chrome, FF and Safari
if document.addEventListener
$(document).on("paste", "[name*=address_1]", #googleMapsAutocompletePasteBugFix)
$(document).on("onpaste", "[name*=address_1]", #googleMapsAutocompletePasteBugFix)
else
for element in $("input[name*=address_1]")
document.getElementById($(element).attr('id')).onpaste = #googleMapsAutocompletePasteBugFix
googleMapsAutocompletePasteBugFix: (e) ->
unless e
e = window.event
if e.srcElement
target = e.srcElement
else
target = e.target
field = $(target)
fieldId = field.attr('id')
focusSwitchFieldId = fieldId.replace(/(\d)$/, '2')
setTimeout(->
if window.chrome || /Safari/.test(navigator.userAgent)
val = field.val()
$("##{focusSwitchFieldId}").focus()
field.val(val)
field.focus()
else
field = document.getElementById(fieldId)
val = field.value
document.getElementById(focusSwitchFieldId).focus()
setTimeout(->
field.value = val
field.focus()
field.focus()
, 50)
, 10)

Related

How to defocus a cursor from an input text field in protractor

I have an input text field filled with date. I have to clear the date text and click cursor to somewhere on webpage or to some element to do other actions.
Now the problem is I am unable to move cursor to some other element or somewhere on webpage. Cursor remains on that input box once text is cleared
I have tried following ways:
mouseMove: I am trying to move cursor to somewhere on webpage and clicking it but not working.
blur() : used this one to loose the focus but not working.
var input = element(by.css('input[placeholder = "Choose a date"]'))
var someOtherElement = element(by.id('otherElement'));
input.click().clear().then((function) {
browser.actions().mouseMove(someOtherElement).click().perform();
});
Actual: Once date text is cleared, cursor remains on the text input. it is not moving from that text box.
Expected: I wanna cursor loose the focus and move to some other element and click it so that I can do some other actions.
Do you get any error stack for this? Would be great if you paste it here.
I am actually suspecting that someOtherElement does not exist or not clickable.
Can you give below snippet also a shot by making the function which have below code in it as async()?
var input = await element(by.css('input[placeholder = "Choose a date"]'));
var someOtherElement = await element(by.id('otherElement'));
await input.click().clear().then(() => {
someOtherElement.click();
})
.then(() => console.log('finished'));

How to enable auto focus on SAPUI5 input suggestion field

I'm currently developing a sapui5 mobile application and am using an sap.m.Input with suggestions bound by a model like this:
new Page('page', {
showNavButton: true,
content: [
new sap.m.Input({
id: "input",
type: 'Text',
showSuggestion: true,
suggestionItemSelected: function(event) {
event.getParameters().selectedItem.mProperties.text;
},
liveChange: function() {
// some stuff
}
})
]
});
The Model is created and bound like the following:
var model = new sap.ui.model.json.JSONModel();
// model is filled
sap.ui.getCore().byId('input').setModel(model);
sap.ui.getCore().byId('input').bindAggregation('suggestionItems', '/', new sap.ui.core.Item({
text: "{someField}"
}));
When I now click into the input field on a mobile device, kind of a new screen opens with a new input field, which the user has to manually focus again, what seems like a usability flaw to me.
Is there a nice possibility to enable auto focusing the input field on this new screen, so that the user doesn't has to do it again? Or can this screen be disabled at all on mobile devices?
sap.m.input doesn't seem to have a own method for focusing, or at least I'm not finding one - I already tried using jquery's .focus() on the new input field, but without success.
edit: for clarification, the suggestion works troublefree - only the absence of the auto focus on the appearing new screen is what bothers me.
Here is a workaround to "fix" this behavior: https://jsbin.com/lukozaq
Note 1: The above snippet relies on internal implementation of how the popup works. Use it with caution as there are currently no public APIs to access the corresponding internal controls.
Note 2: I put the word fix in quotes because it seems to be the intended behavior that the user has to click on the second input field explicitly, according to the comment in the source code:
Setting focus to DOM Element, which can open the on screen keyboard on mobile device, doesn't work consistently across devices. Therefore, setting focus to those elements are disabled on mobile devices and the keyboard should be opened by the user explicitly.
That comment is from the module sap.m.Dialog. On a mobile device, when the user clicks on the source input field, a stretched Dialog opens up as a "popup" which has the second input field in its sub header.
Please check the API documentation of sap.m.Input, it has a method focus. You can call:
this.byId("input").focus()
to set the focus into the input field.
Try this:
jQuery.sap.delayedCall(0, this, function() {
this.byId("input").focus()
});
About how to detect when the user presses the input field: maybe something like this? Only problem is that I think you probably don't know the id of the new input field which is shown.
var domId = this.byId("input").getId();
$( "#"+domId ).click(function() {
jQuery.sap.delayedCall(0, this, function() {
this.byId("input").focus()
});
});
I am pretty sure that the first piece of code is how to put focus on an input. I'm not sure about the second part, but it's something to try.
in onAfterRendering() do the below..
onAfterRendering : function() {
$('document').ready(function(){
sap.ui.getCore().byId('input').focus();
});
}
I didn´t have the exactly same problem, but It was similiar.
My problem was that I needed focus into suggestion input when the view had been rendered. My solution was to put following code into "hanldeRouteMatched" function:
var myInput = this.byId("inputName");
var viewName = this.getView().getId();
var selector1 = viewName + "--inputName-inner";
var selector2 = viewName + "--inputName-popup-input-inner";
jQuery.sap.delayedCall(1000, this, function() {
myInput.focus();
if($("#" + selector1)){
$("#" + selector1).click();
jQuery.sap.delayedCall(500, this, function() {
if($("#" + selector2)){
$("#" + selector2).focus();
}
});
}
});
If you see that suggestion input catch focus, but It lose it after, or It never catched it, try increasing the time in delayedCalls. The needed time depends on your connection speed.

TinyMCE 3 - textarea id which fired blur event

When a TinyMCE editor blur occurs, I am trying to find the element id (or name) of the textarea which fired the blur event. I also want the element id (or name) of the element which gains the focus, but that part should be similar.
I'm getting closer in being able to get the iframe id of the tinymce editor, but I've only got it working in Chrome and I'm sure there is a better way of doing it. I need this to work across different browsers and devices.
For example, this below code returns the iframe id in Chrome which is okay since the iframe id only appends a suffix of "_ifr" to my textarea element id. I would prefer the element id of the textarea, but it's okay if I need to remove the iframe suffix.
EDIT: I think it's more clear if I add a complete TinyMCE Fiddle (instead of the code below):
http://fiddle.tinymce.com/HIeaab/1
setup : function(ed) {
ed.onInit.add(function(ed) {
ed.pasteAsPlainText = true;
/* BEGIN: Added this to handle JS blur event */
/* example modified from: http://tehhosh.blogspot.com/2012/06/setting-focus-and-blur-event-for.html */
var dom = ed.dom,
doc = ed.getDoc(),
el = doc.content_editable ? ed.getBody() : (tinymce.isGecko ? doc : ed.getWin());
tinymce.dom.Event.add(el, 'blur', function(e) {
//console.log('blur');
var event = e || window.event;
var target = event.target || event.srcElement;
console.log(event);
console.log(target);
console.log(target.frameElement.id);
console.log('the above outputs the following iframe id which triggered the blur (but only in Chrome): ' + 'idPrimeraVista_ifr');
})
tinymce.dom.Event.add(el, 'focus', function(e) {
//console.log('focus');
})
/* END: Added this to handle JS blur event */
});
}
Maybe it's better to give a background of what I'm trying to accomplish:
We have multiple textareas on a form which we're trying to "grammarcheck" with software called "languagetool" (that uses TinyMCE version 3.5.6). Upon losing focus on a textarea, we would like to invoke the grammarcheck for the textarea that lost focus and then return the focus to where it's supposed to go after the grammar check.
I've struggled with this for quite some time, and would greatly appreciate any feedback (even if it's general advice for doing this differently).
Many Thanks!
Simplify
TinyMCE provides a property on the Editor object for getting the editor instance ID: Editor.id
It also seems overkill to check for doc.content_editable and tinyMCE.isGecko because Editor.getBody() allows for cross-browser compatible event binding already (I checked IE8-11, and latest versions of Firefox and Chrome).
Note: I actually found that the logic was failing to properly assign ed.getBody() to el in Internet Explorer, so it wasn't achieving the cross-browser functionality you need anyway.
Try the following simplified event bindings:
tinyMCE.init({
mode : "textareas",
setup : function (ed) {
ed.onInit.add(function (ed) {
/* onBlur */
tinymce.dom.Event.add(ed.getBody(), 'blur', function (e) {
console.log('Editor with ID "' + ed.id + '" has blur.');
});
/* onFocus */
tinymce.dom.Event.add(ed.getBody(), 'focus', function (e) {
console.log('Editor with ID "' + ed.id + '" has focus.');
});
});
}
});
…or see this working TinyMCE Fiddle »
Aside: Your Fiddle wasn't properly initializing the editors because the plugin was failing to load. Since you don't need the plugin for this example, I removed it from the Fiddle to get it working.

can't tap on item in google autocomplete list on mobile

I'm making a mobile-app using Phonegap and HTML. Now I'm using the google maps/places autocomplete feature. The problem is: if I run it in my browser on my computer everything works fine and I choose a suggestion to use out of the autocomplete list - if I deploy it on my mobile I still get suggestions but I'm not able to tap one. It seems the "suggestion-overlay" is just ignored and I can tap on the page. Is there a possibility to put focus on the list of suggestions or something that way ?
Hope someone can help me. Thanks in advance.
There is indeed a conflict with FastClick and PAC. I found that I needed to add the needsclick class to both the pac-item and all its children.
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
There is currently a pull request on github, but this hasn't been merged yet.
However, you can simply use this patched version of fastclick.
The patch adds the excludeNode option which let's you exclude DOM nodes handled by fastclick via regex. This is how I used it to make google autocomplete work with fastclick:
FastClick.attach(document.body, {
excludeNode: '^pac-'
});
This reply may be too late. But might be helpful for others.
I had the same issue and after debugging for hours, I found out this issue was because of adding "FastClick" library. After removing this, it worked as usual.
So for having fastClick and google suggestions, I have added this code in geo autocomplete
jQuery.fn.addGeoComplete = function(e){
var input = this;
$(input).attr("autocomplete" , "off");
var id = input.attr("id");
$(input).on("keypress", function(e){
var input = this;
var defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(37.2555, -121.9245),
new google.maps.LatLng(37.2555, -121.9245));
var options = {
bounds: defaultBounds,
mapkey: "xxx"
};
//Fix for fastclick issue
var g_autocomplete = $("body > .pac-container").filter(":visible");
g_autocomplete.bind('DOMNodeInserted DOMNodeRemoved', function(event) {
$(".pac-item", this).addClass("needsclick");
});
//End of fix
autocomplete = new google.maps.places.Autocomplete(document.getElementById(id), options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
//Handle place selection
});
});
}
if you are using Framework 7, it has a custom implementation of FastClicks. Instead of the needsclick class, F7 has no-fastclick. The function below is how it is implemented in F7:
function targetNeedsFastClick(el) {
var $el = $(el);
if (el.nodeName.toLowerCase() === 'input' && el.type === 'file') return false;
if ($el.hasClass('no-fastclick') || $el.parents('.no-fastclick').length > 0) return false;
return true;
}
So as suggested in other comments, you will only have to add the .no-fastclick class to .pac-item and in all its children
I was having the same problem,
I realized what the problem was that probably the focusout event of pac-container happens before the tap event of the pac-item (only in phonegap built-in browser).
The only way I could solve this, is to add padding-bottom to the input when it is focused and change the top attribute of the pac-container, so that the pac-container resides within the borders of the input.
Therefore when user clicks on item in list the focusout event is not fired.
It's dirty, but it works
worked perfectly for me :
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
Configuration: Cordova / iOS iphone 5

iOS 5 fixed positioning and virtual keyboard

I have a mobile website which has a div pinned to the bottom of the screen via position:fixed. All works fine in iOS 5 (I'm testing on an iPod Touch) until I'm on a page with a form. When I tap into an input field and the virtual keyboard appears, suddenly the fixed position of my div is lost. The div now scrolls with the page as long as the keyboard is visible. Once I click Done to close the keyboard, the div reverts to its position at the bottom of the screen and obeys the position:fixed rule.
Has anyone else experienced this sort of behavior? Is this expected? Thanks.
I had this problem in my application. Here's how I'm working around it:
input.on('focus', function(){
header.css({position:'absolute'});
});
input.on('blur', function(){
header.css({position:'fixed'});
});
I'm just scrolling to the top and positioning it there, so the iOS user doesn't notice anything odd going on. Wrap this in some user agent detection so other users don't get this behavior.
I had a slightly different ipad issue where the virtual keyboard pushed my viewport up offscreen. Then after the user closed the virtual keyboard my viewport was still offscreen. In my case I did something like the following:
var el = document.getElementById('someInputElement');
function blurInput() {
window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
This is the code we use to fix problem with ipad. It basically detect discrepancies between offset and scroll position - which means 'fixed' isn't working correctly.
$(window).bind('scroll', function () {
var $nav = $(".navbar")
var scrollTop = $(window).scrollTop();
var offsetTop = $nav.offset().top;
if (Math.abs(scrollTop - offsetTop) > 1) {
$nav.css('position', 'absolute');
setTimeout(function(){
$nav.css('position', 'fixed');
}, 1);
}
});
The position fixed elements simply don't update their position when the keyboard is up. I found that by tricking Safari into thinking that the page has resized, though, the elements will re-position themselves. It's not perfect, but at least you don't have to worry about switching to 'position: absolute' and tracking changes yourself.
The following code just listens for when the user is likely to be using the keyboard (due to an input being focused), and until it hears a blur it just listens for any scroll events and then does the resize trick. Seems to be working pretty well for me thus far.
var needsScrollUpdate = false;
$(document).scroll(function(){
if(needsScrollUpdate) {
setTimeout(function() {
$("body").css("height", "+=1").css("height", "-=1");
}, 0);
}
});
$("input, textarea").live("focus", function(e) {
needsScrollUpdate = true;
});
$("input, textarea").live("blur", function(e) {
needsScrollUpdate = false;
});
Just in case somebody happens upon this thread as I did while researching this issue. I found this thread helpful in stimulating my thinking on this issue.
This was my solution for this on a recent project. You just need to change the value of "targetElem" to a jQuery selector that represents your header.
if(navigator.userAgent.match(/iPad/i) != null){
var iOSKeyboardFix = {
targetElem: $('#fooSelector'),
init: (function(){
$("input, textarea").on("focus", function() {
iOSKeyboardFix.bind();
});
})(),
bind: function(){
$(document).on('scroll', iOSKeyboardFix.react);
iOSKeyboardFix.react();
},
react: function(){
var offsetX = iOSKeyboardFix.targetElem.offset().top;
var scrollX = $(window).scrollTop();
var changeX = offsetX - scrollX;
iOSKeyboardFix.targetElem.css({'position': 'fixed', 'top' : '-'+changeX+'px'});
$('input, textarea').on('blur', iOSKeyboardFix.undo);
$(document).on('touchstart', iOSKeyboardFix.undo);
},
undo: function(){
iOSKeyboardFix.targetElem.removeAttr('style');
document.activeElement.blur();
$(document).off('scroll',iOSKeyboardFix.react);
$(document).off('touchstart', iOSKeyboardFix.undo);
$('input, textarea').off('blur', iOSKeyboardFix.undo);
}
};
};
There is a little bit of a delay in the fix taking hold because iOS stops DOM manipulation while it is scrolling, but it does the trick...
None of the other answers I've found for this bug have worked for me. I was able to fix it simply by scrolling the page back up by 34px, the amount mobile safari scrolls it down. with jquery:
$('.search-form').on('focusin', function(){
$(window).scrollTop($(window).scrollTop() + 34);
});
This obviously will take effect in all browsers, but it prevents it breaking in iOS.
This issue is really annoying.
I combined some of the above mentioned techniques and came up with this:
$(document).on('focus', 'input, textarea', function() {
$('.YOUR-FIXED-DIV').css('position', 'static');
});
$(document).on('blur', 'input, textarea', function() {
setTimeout(function() {
$('.YOUR-FIXED-DIV').css('position', 'fixed');
$('body').css('height', '+=1').css('height', '-=1');
}, 100);
});
I have two fixed navbars (header and footer, using twitter bootstrap).
Both acted weird when the keyboard is up and weird again after keyboard is down.
With this timed/delayed fix it works. I still find a glitch once in a while, but it seems to be good enough for showing it to the client.
Let me know if this works for you. If not we might can find something else. Thanks.
I was experiencing same issue with iOS7. Bottom fixed elements would mess up my view not focus properly.
All started working when I added this meta tag to my html.
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,height=device-height" >
The part which made the difference was:
height=device-height
Hope that helps someone.
I've taken Jory Cunningham answer and improved it:
In many cases, it's not just one element who goes crazy, but several fixed positioned elements, so in this case, targetElem should be a jQuery object which has all the fixed elements you wish to "fix". Ho, this seems to make the iOS keyboard go away if you scroll...
Needless to mention you should use this AFTER document DOM ready event or just before the closing </body> tag.
(function(){
var targetElem = $('.fixedElement'), // or more than one
$doc = $(document),
offsetY, scrollY, changeY;
if( !targetElem.length || !navigator.userAgent.match(/iPhone|iPad|iPod/i) )
return;
$doc.on('focus.iOSKeyboardFix', 'input, textarea, [contenteditable]', bind);
function bind(){
$(window).on('scroll.iOSKeyboardFix', react);
react();
}
function react(){
offsetY = targetElem.offset().top;
scrollY = $(window).scrollTop();
changeY = offsetY - scrollY;
targetElem.css({'top':'-'+ changeY +'px'});
// Instead of the above, I personally just do:
// targetElem.css('opacity', 0);
$doc.on('blur.iOSKeyboardFix', 'input, textarea, [contenteditable]', unbind)
.on('touchend.iOSKeyboardFix', unbind);
}
function unbind(){
targetElem.removeAttr('style');
document.activeElement.blur();
$(window).off('scroll.iOSKeyboardFix');
$doc.off('touchend.iOSKeyboardFix blur.iOSKeyboardFix');
}
})();
I have a solution similar to #NealJMD except mine only executes for iOS and correctly determines the scroll offset by measuring the scollTop before and after the native keyboard scrolling as well as using setTimeout to allow the native scrolling to occur:
var $window = $(window);
var initialScroll = $window.scrollTop();
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
setTimeout(function () {
$window.scrollTop($window.scrollTop() + (initialScroll - $window.scrollTop()));
}, 0);
}
I have fixed my Ipad main layout content fixed position this way:
var mainHeight;
var main = $('.main');
// hack to detects the virtual keyboard close action and fix the layout bug of fixed elements not being re-flowed
function mainHeightChanged() {
$('body').scrollTop(0);
}
window.setInterval(function () {
if (mainHeight !== main.height())mainHeightChanged();
mainHeight = main.height();
}, 100);
I had a similar problem to #ds111 s. My website was pushed up by the keyboard but didn't move down when the keyboard closed.
First I tried #ds111 solution but I had two input fields. Of course, first the keyboard goes away, then the blur happens (or something like that). So the second input was under the keyboard, when the focus switched directly from one input to the other.
Furthermore, the "jump up" wasn't good enough for me as the whole page only has the size of the ipad. So I made the scroll smooth.
Finally, I had to attach the event listener to all inputs, even those, that were currently hidden, hence the live.
All together I can explain the following javascript snippet as:
Attach the following blur event listener to the current and all future input and textarea (=live): Wait a grace period (= window.setTimeout(..., 10)) and smoothly scroll to top (= animate({scrollTop: 0}, ...)) but only if "no keyboard is shown" (= if($('input:focus, textarea:focus').length == 0)).
$('input, textarea').live('blur', function(event) {
window.setTimeout(function() {
if($('input:focus, textarea:focus').length == 0) {
$("html, body").animate({ scrollTop: 0 }, 400);
}
}, 10)
})
Be aware, that the grace period (= 10) may be too short or the keyboard may still be shown although no input or textarea is focused. Of course, if you want the scrolling faster or slower, you may adjust the duration (= 400)
really worked hard to find this workaround, which in short looks for focus and blur events on inputs, and scrolling to selectively change the positioning of the fixed bar when the events happen. This is bulletproof, and covers all cases (navigating with <>, scroll, done button). Note id="nav" is my fixed footer div. You can easily port this to standard js, or jquery. This is dojo for those who use power tools ;-)
define([
"dojo/ready",
"dojo/query",
], function(ready, query){
ready(function(){
/* This addresses the dreaded "fixed footer floating when focusing inputs and keybard is shown" on iphone
*
*/
if(navigator.userAgent.match(/iPhone/i)){
var allInputs = query('input,textarea,select');
var d = document, navEl = "nav";
allInputs.on('focus', function(el){
d.getElementById(navEl).style.position = "static";
});
var fixFooter = function(){
if(d.activeElement.tagName == "BODY"){
d.getElementById(navEl).style.position = "fixed";
}
};
allInputs.on('blur', fixFooter);
var b = d.body;
b.addEventListener("touchend", fixFooter );
}
});
}); //end define
This is a difficult problem to get 'right'. You can try and hide the footer on input element focus, and show on blur, but that isn't always reliable on iOS. Every so often (one time in ten, say, on my iPhone 4S) the focus event seems to fail to fire (or maybe there is a race condition), and the footer does not get hidden.
After much trial and error, I came up with this interesting solution:
<head>
...various JS and CSS imports...
<script type="text/javascript">
document.write( '<style>#footer{visibility:hidden}#media(min-height:' + ($( window ).height() - 10) + 'px){#footer{visibility:visible}}</style>' );
</script>
</head>
Essentially: use JavaScript to determine the window height of the device, then dynamically create a CSS media query to hide the footer when the height of the window shrinks by 10 pixels. Because opening the keyboard resizes the browser display, this never fails on iOS. Because it's using the CSS engine rather than JavaScript, it's much faster and smoother too!
Note: I found using 'visibility:hidden' less glitchy than 'display:none' or 'position:static', but your mileage may vary.
Works for me
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
$(document).on('focus', 'input, textarea', function() {
$('header').css({'position':'static'});
});
$(document).on('blur', 'input, textarea', function() {
$('header').css({'position':'fixed'});
});
}
In our case this would fix itself as soon as user scrolls. So this is the fix we've been using to simulate a scroll on blur on any input or textarea:
$(document).on('blur', 'input, textarea', function () {
setTimeout(function () {
window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
}, 0);
});
My answer is that it can't be done.
I see 25 answers but none work in my case. That's why Yahoo and other pages hide the fixed header when the keyboard is on. And Bing turns the whole page non-scrollable (overflow-y: hidden).
The cases discussed above are different, some have issues when scrolling, some on focus or blur. Some have fixed footer, or header. I can't test now each combination, but you might end up realizing that it can't be done in your case.
Found this solution on Github.
https://github.com/Simbul/baker/issues/504#issuecomment-12821392
Make sure you have scrollable content.
// put in your .js file
$(window).load(function(){
window.scrollTo(0, 1);
});
// min-height set for scrollable content
<div id="wrap" style="min-height: 480px">
// website goes here
</div>
The address bar folds up as an added bonus.
In case anyone wanted to try this. I got the following working for me on a fixed footer with an inputfield in it.
<script>
$('document').ready(
function() {
if (navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)
|| navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i)) {
var windowHeight = $(window).height();
var documentHeight = $(document).height();
$('#notes').live('focus', function() {
if (documentHeight > windowHeight) {
$('#controlsContainer').css({
position : 'absolute'
});
$("html, body").animate({
scrollTop : $(document).height()
}, 1);
}
});
$('#notes').live('blur', function() {
$('#controlsContainer').css({
position : 'fixed'
});
$("html, body").animate({
scrollTop : 0
}, 1);
});
}
});
</script>
I have the same issue. But I realized that the fixed position is just delayed and not broken (at least for me). Wait 5-10 seconds and see if the div adjusts back to the bottom of the screen. I believe it's not an error but a delayed response when the keyboard is open.
I tried all the approaches from this thread, but if they didn't help, they did even worse.
In the end, I decided force device to loose focus:
$(<selector to your input field>).focus(function(){
var $this = $(this);
if (<user agent target check>) {
function removeFocus () {
$(<selector to some different interactive element>).focus();
$(window).off('resize', removeFocus);
}
$(window).on('resize', removeFocus);
}
});
and it worked like a charm and fixed my sticky login-form.
Please NOTE:
The JS code above is only to present my idea, to execute this snippet please replace values in angular braces (<>) with appropriate values for your situation.
This code is designed to work with jQuery v1.10.2
This is still a large bug for for any HTML pages with taller Bootstrap Modals in iOS 8.3. None of the proposed solutions above worked and after zooming in on any field below the fold of a tall modal, Mobile Safari and/or WkWebView would move the fixed elements to where the HTML body's scroll was situated, leaving them misaligned with where they actually where laid out.
To workaround the bug, add an event listener to any of your modal inputs like:
$(select.modal).blur(function(){
$('body').scrollTop(0);
});
I'm guessing this works because forcing the HTML body's scroll height re-aligns the actual view with where the iOS 8 WebView expects the fixed modal div's contents to be.
If anybody was looking for a completely different route (like you are not even looking to pin this "footer" div as you scroll but you just want the div to stay at the bottom of the page), you can just set the footer position as relative.
That means that even if the virtual keyboard comes up on your mobile browser, your footer will just stay anchored to the bottom of the page, not trying to react to virtual keyboard show or close.
Obviously it looks better on Safari if position is fixed and the footer follows the page as you scroll up or down but due to this weird bug on Chrome, we ended up switching over to just making the footer relative.
None of the scrolling solutions seemed to work for me. Instead, what worked is to set the position of the body to fixed while the user is editing text and then restore it to static when the user is done. This keeps safari from scrolling your content on you. You can do this either on focus/blur of the element(s) (shown below for a single element but could be for all input, textareas), or if a user is doing something to begin editing like opening a modal, you can do it on that action (e.g. modal open/close).
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
iOS9 - same problem.
TLDR - source of the problem. For solution, scroll to bottom
I had a form in a position:fixed iframe with id='subscribe-popup-frame'
As per the original question, on input focus the iframe would go to the top of the document as opposed to the top of the screen.
The same problem did not occur in safari dev mode with user agent set to an idevice. So it seems the problem is caused by iOS virtual keyboard when it pops up.
I got some visibility into what was happening by console logging the iframe's position (e.g. $('#subscribe-popup-frame', window.parent.document).position() ) and from there I could see iOS seemed to be setting the position of the element to {top: -x, left: 0} when the virtual keyboard popped up (i.e. focussed on the input element).
So my solution was to take that pesky -x, reverse the sign and then use jQuery to add that top position back to the iframe. If there is a better solution I would love to hear it but after trying a dozen different approaches it was the only one that worked for me.
Drawback: I needed to set a timeout of 500ms (maybe less would work but I wanted to be safe) to make sure I captured the final x value after iOS had done its mischief with the position of the element. As a result, the experience is very jerky . . . but at least it works
Solution
var mobileInputReposition = function(){
//if statement is optional, I wanted to restrict this script to mobile devices where the problem arose
if(screen.width < 769){
setTimeout(function(){
var parentFrame = $('#subscribe-popup-frame',window.parent.document);
var parentFramePosFull = parentFrame.position();
var parentFramePosFlip = parentFramePosFull['top'] * -1;
parentFrame.css({'position' : 'fixed', 'top' : parentFramePosFlip + 'px'});
},500);
}
}
Then just call mobileInputReposition in something like $('your-input-field).focus(function(){}) and $('your-input-field).blur(function(){})