Using .scrollTop animation with mobile device not working - javascript

I have a footer that appears when a user scrolls down on the bottom of the page, but for seem reason it doesn't appear to be working on mobile devices, particularly the ipad, and it seems finicky on there. Sometimes it works sometimes it doesn't and only when using the ipad vertically.
<script type="text/javascript">
var $window = jQuery(window);
var $document = jQuery(document);
var footer = jQuery('.footer');
footer.css({opacity: 0});
$window.on('scroll', function() {
if (($window.scrollTop() + $window.innerHeight()) == $document.height()) {
footer.stop(true).animate({opacity: 1}, 250);
}
else {
footer.stop(true).animate({opacity: 0}, 250);
}
});
</script>
Just fades in and out on the bottom of the page condition. I looked around and there seems to be several ways to go about doing this and I was wanting to know the most effective solution.
I thought I had found a jfiddle for a solution a while ago but can't seem to find that question anymore and it required me to dig quite a bit.
I'm not exactly sure all of the factors that go into mobile not being compatible with this solution I currently have, so it's hard for me to determine what needs adjusting. Thanks.

Actually figured out the issue is that it needs to be the exact document height if I'm using '==', in mobile devices the viewpoint doesn't trigger the script while moving or scrolling so I had t change the '==' to '>=' in my condition and then add height to my viewport.
if (($window.scrollTop() + $window.innerHeight()) >= $document.height())
And in my header viewport tag
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
And it works perfectly!

Related

Wrong value for window.innerWidth during onload event in Firefox for Android?

Okay, so, the problem I am facing is this: my mobile Firefox browser is not retrieving the correct values for window.innerWidth, document.documentElement.clientWidth, or even the width of a div styled to take up the whole client window after page load.
I am not crazy, my code works just fine in every other browser! For some reason Firefox initializes these values with defaults and then gets the correct values later on. If at any point I interrupt my JavaScript with an alert(), these properties magically become accurate afterwards.
I have scoured the internet for an answer and all I can find is a hack workaround: use window.setTimeout to delay the use of these properties until they have time to populate correctly. That is crazy! Users want speed, not an extra delay just to view my site on a Firefox browser.
What I don't understand is that I can set a div up to fill the client window perfectly before the values become accurate. I do this in css by setting width and height of my div's id to 100%. document.documentElement is basically the same as document.getElementById("my_div"); after all the document elements have loaded, so, how does the browser know how big the div should be when it doesn't have the correct dimensions of the client window in the first place?
I have tried running my code inside a window.addEventListener("load",function(event_){ //My Code }); but still these values will not generate. Is there a page load event that comes after window.onload?
If anyone can tell me why only Firefox mobile seems to display this odd behavior I will give you a mental high five.
Here's a bit of sample code for recreating the problem:
<!DOCTYPE HTML>
<html>
<head>
<!-- Added " after javascript during edit. -->
<script type="text/javascript">
window.addEventListener("load",function(event_){
var output=document.getElementById("output");
/* Returns some default value like 980. */
output.innerHTML=window.innerWidth;
alert("After this alert, the value will change.");
/* Returns an accurate value like 511. */
output.innerHTML=window.innerWidth;
});
</script>
<!-- Added title during edit. -->
<title>Title</title>
</head>
<body>
<p id="output">Default Output</p>
</body>
</html>
My Firefox for android version is 35.0.1. My Android version is 4.4.4. On my device, Firefox displays "980" in the output p element, shows the alert, and then displays "980" again. After page refresh, the first two steps remain the same, but the output after the alert changes to 360. This happens with document.documentElement.clientWidth as well. No properties I try seem to get the correct values. It seems that Firefox has some sort of delay after page load before it has access to the client window's dimensions...
I tried the verge.airve.com plugin without JQuery and its initial feedback remained at 980. It also initialized as 980 on Chrome, which was weird, because Chrome worked as expected without it...
After much debate a solution was found! Firefox apparently resizes the window after it is loaded (I guess for good measure, who really knows)! So, by adding a resize event handler in addition to window.onload, this problem can be averted! See accepted answer below for more details.
Make sure your measurement is done when whole document is loaded and resized.
window.onload = showViewport;
window.onresize = showViewport;
function showViewport() {
var output=document.getElementById("output");
var width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var height= Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
output.innerHTML = "Viewport size is " + width + "x" + height;
}
<body>
<p id="output">Default Output</p>
</body>
The problem (innerWidth === 980) persists for Firefox 40.0 under Android 4.4.4. A 1 msec wait is a circumvention. Replace window.onload = myProgram; by
window.onload = function() {setTimeout(myProgram, 1)};
In the meantime I encountered this problem while adapting a fairly elaborate site to small screens. Firefox obeys the CSS following "#media only screen and (max-width: 768px)". However, when one tries to set event handlers depending on device widths, Firefox fails miserably. I needed the above trick with 0.5 second wait at all spots where I picked up the device width. This wait time was necessary for Nexus 7 (2012), but who knows what is needed for other devices?
I can confirm the issue, for example in Firefox 38.0.1 on Android 4.1.2. Created a js bin for testing purposes.
I'd like to check window.innerWidth for custom DOM manipulations on different resolutions (mobile, tablet and desktop size), so it'd be important to get the correct window.innerWidth value already in the document.ready() state and not just only in the window.load().
$('#inline').html($(window).width());
$(document).ready(function() {
$('#ready').html(window.innerWidth);
});
$(window).load(function() {
$('#load').html(window.innerWidth);
});
setTimeout(function() {
$('#setTimeout').html(window.innerWidth);
}, 1000);
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JS Bin</title>
</head>
<body>
<p><span id="inline"></span></p>
<p>$(document).ready(): <span id="ready"></span></p>
<p>$(window).load(): <span id="load"></span></p>
<p>setTimeout(1000): <span id="setTimeout"></span></p>
</body>
</html>
(I wanted to add only a comment, and not answer, but no reputations yet to do so :-)
I was facing the same issue while using BrowserComponent in CodeNameOne and Android
My solution was to put the js inside a function like so
function runScripts()
{
//get width here
}
And listen to the onLoad event of the BrowserComponent to execute this script once the browser has been fully loaded
like so:
BrowserComponent browser = new BrowserComponent();
browser.addWebEventListener("onLoad", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
browser.execute("runScripts()");
}
});
browser.setURL("http://www.URL.com");
Handling window.onload in the html wasn't enough to wait for the appropriate width to be served
Besides this solution I also found that window.setTimeout(runScripts, 500); works to get the right document width, at the expense of wasting half a second
window.setTimeout(yourFunction, 1);
This did the job for me, 1ms is enough.
A very hack solution I found is to invoke a fake link in the header. My guess is the time delay allows updating of window.innerWidth and window.innerHeight prior to script execution.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/fake.css"/>
I had the same problem, getting varying width when fetching window.innerWidth on an android device with Firefox. I tried some of the suggestions above, but without success - possibly implementing the examples in a wrong way?
However, by using the code below, I got a system that seems to be working 100% as far as I have tested. It also makes little delay as it break the loop as soon as it get a stable result.
var canvasWidth = 0;
var canvasHeight = 0;
var previousWidth = -1;
var previousHeight = -1;
while ((canvasWidth != previousWidth) || (canvasHeight != previousHeight))
{
previousWidth = canvasWidth;
previousHeight = canvasHeight;
canvasWidth = window.innerWidth;
canvasHeight = window.innerHeight;
}

Browser width for mobile

I have a Nexus 5, and when I go to http://ryanve.com/lab/dimensions/, it tells me that my width 360. I understand that there is a difference between my phone's resolution and the width of my browser.
However, when I write a function to change at under 767:
function detectmob() {
if($(window).width() <= 767) {
return true;
}
else {
return false;
}
}
if (detectmob()){
}
else {
}
It doesn't work on my phone. If I resize my browser window width to be <= 767 on my laptop, the function works correctly. When I view it on my Nexus 5, it doesn't.
Could anyone help me write a function to target mobile devices using the browser width?
When you visit a website via a mobile browser it will assume that you're viewing a big desktop experience and that you want to see all of it, not just the top left corner. It will therefore set the viewport width at (in the case of iOS Safari) 980px, shoe-horning everything into its little display.
The Viewport Meta Tag
Enter the viewport meta tag, introduced by Apple, then adopted and developed further by others.
It looks like this:
<meta name="viewport" content="">
Within the content="" you can enter a load of comma delimited values, but we're going to to focus on the fundamental ones for now.
For example, if your mobile design is purposely laid out at 320px you can specify the viewport width:
<meta name="viewport" content="width=320">
http://webdesign.tutsplus.com/articles/quick-tip-dont-forget-the-viewport-meta-tag--webdesign-5972

Mobile Safari: why is window.scrollTo(0, 0) not scrolling to (0, 0)?

I've built a small single-page web app using Bootstrap 3, Sammy.js and Knockout 3. I'm finding that when the page is scrolled down, I'm unable to get window.scrollTo(0, 0) to work on Mobile Safari when I also change location.hash - specifically on iOS 7 on an iPhone 5C (likely happens on other iPhone models though).
When I try something like this:
self.changeState = function() {
self.state(State.NewState);
location.hash = 'somevalue';
window.scrollTo(0, 0);
};
The page will scroll almost all the way to the top - it will usually be scrolled to Y = 12 or 13. It will never scroll to 0 if I call window.scrollTo(0, 0); when the user is scrolled to the bottom of the page (and the content is sufficiently high to warrant a scroll to top).
I've tried various StackOverflow answers/suggestions (e.g. The same old issue, .scrollTop(0) not working in Chrome & Safari); the usual remedies (wrap in a setTimeout) do not change the behavior - it still scrolls to somewhere near the top of the page, but not quite to the top.
Header style:
<div class="navbar navbar-default navbar-inverse navbar-static-top">
Viewport settings:
<meta name="viewport"
content="width=device-width,
height=device-height,
initial-scale=1.0,
maximum-scale=1.0,
target-densityDpi=device-dpi" />
Scroll attempts:
self.changeState = function() {
self.state(State.NewState);
location.hash = 'somevalue';
window.scrollTo(0, 0);
};
and:
self.changeState = function() {
self.state(State.NewState);
location.hash = 'somevalue';
window.setTimeout(function() {
window.scrollTo(0, 0);
}, 0);
};
I've dug into this with the Safari Web Inspector, and nothing seems out of place as far as the structure of the page. I'm just not sure what to look for here - any ideas?
Edit:
So far, I have not been able to reproduce this outside of my app's code. I'm trying to get this to break in a JSFiddle - in this one, it works correctly (e.g., it scrolls to 0,0 as it should): http://jsfiddle.net/rringham/n9evU/24/show.
I managed to recreate this issue by using height: 100vh or min-height: 100vh on elements. I changed my CSS to use 100% instead (which is a bit of a pain) and the problem disappeared.
Try setting scrollTo(-n, 0); "n" being any number lower than 0
One trick to achieve this:
window.scrollTo(0, 0);
setTimeout(() => { window.scrollTo(0, 0); }, 100);
In my case, same issue, but it were coming from the fact I was in an iframe.
So doing window.top.scrollTo(0,0) made it!!!!

Bootstrap3 + IE9: Navbar not expanding

Please see this website I'm developing for a client:
http://tinyurl.com/ot8fljg
The top menu is a bootstrap3 navbar. I've modified it with a small piece of js code, to make the submenu show on hover instead of click, like so:
$(function() {
$('li.dropdown.hover').hover(
function(e) { $(this).addClass('open'); },
function(e) { $(this).removeClass('open'); }
);
});
However, it just won't show on IE9. I've been playing with IE's built-in developer tools for hours now, and I just can't seem to find the solution. Could anybody help me understand why it's only showing submenu borders on IE9?
check whether your ie9 is in compatible view mode or not. so try this code: <meta http-equiv="X-UA-Compatible" content="IE=edge">

Automatic height resize of an iframe, problems with chrome and safari

I need to include an iframe in a page and I want to calculate the correct height and adjust it in order to avoid displaying the vertical scrollbar. I want to display the horizontal scrollbar, though, if needed.
I've found several posts about this problem, but no one works 100%. This is a very common approach I've seen:
$(document).ready(function() {
$('iframe').load(function() {
$("#your-iframe-id").height($("#your-iframe-id").contents().find("html").height()+35);
});
})
<iframe id="your-iframe-id" style="width:100%;border:0;" src="test.php"></iframe>
The problem I've found with this approach is that, with Safari and Chrome, if, navigating into the iframe, I visit a page which is shorter than the previous one, the height of the frame is still the one of the taller page. If, instead, you navigate from a short page to a tall one, everything is working fine. Firefox doesn't have this problem; I didn't try with IE and Opera.
Any help is really appreciated. Thanks in advance.
<script>
var resizeHandle = function()
{
var theFrame = $('.window-content-wrapper', parent.document.body);
theFrame.height($(document).height());
var theFrame = $('.window-content', parent.document.body);
theFrame.height($(document).height());
};
</script>
<iframe id ="home" onResize="resizeHandle()" onload="resizeHandle()" style="width:100%;border:0;" src="test.php"></iframe>

Categories