I have been writing a small script that shortens documents that are being output on a JSON feed of mine.
I realised that with longer messages, on minimising it could skip a few and you'd have to scroll back to find where you were and so added a scroll function to take you back to the top of the message on minifying. This turned out to be quite annoying when it fired every single time - so I thought, why not make it fire only when the top of the element is above the screen?
And this is where I am stuck --> $(window).scrollTop(); simply doesn't want to output the screen height for me, it's infuriating. I tried with different browsers and the only one .scrollTop() worked for correctly was Internet Explorer.
Here is the function below:
function jexpand(id){
var elm=$('#d'+jdesc[id].i); // element
var ofs=elm.offset().top; // element height - works fine
var top=$(window).scrollTop(); // Y U NO WORK?!!!
if(jdesc[id].e==true){ // boolean to check whether to expand or contract
jdesc[id].e=false; // change boolean flag
if(ofs < top) $('html').animate({scrollTop:($('#'+jdesc[id].i).offset().top)-(20)+'px'},'slow'); // animate to top minus 20 pixels
elm.html(jdesc[id].d.substring(0,347)+'...<br><div class="readmore"><span id="'+id+'">Show More</span></div>');
}else{
jdesc[id].e=true;
elm.html(jdesc[id].d+'<br><div class="readmore"><span id="'+id+'">Show Less</span></div>');
}
$('.readmore span').click(function(){jexpand(this.id)}); // reset click trigger
//alert(top+' <-> '+ofs);
}
When I uncomment the alert() at the bottom in a browser other than IE (I tried chrome, mozilla, chrome android, boat browser android) I get a message akin to:
[object Window] <-> 1077.5625
[object Window] is obviously not a number that can be greater or less than the element height! So what does this mean, is there another flag I need to ask of it? At first I assumed it might be the wrong element I was refering so tried top=$('body').scrollTop();, html, etc, I even tried using div wrapper elements but to no avail.
I am using jquery 1.11.0 and with 1.9.1 I had the same issue.
Am I trying to return the screen top in the wrong way or have all my browsers gone loopy?
EDIT:
Weirdly I've found an issue which may explain things a little, when I typed $(document).scrollTop() into a console it gave me the correct screen height however if I make a var top; outside of the function I get this error 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead..
I am using a webkit borrowed from html5up and this is somehow interfering with the code. Now to find out what it is....
Sorry for the confusion, without this script everything works fine grr...
Try this way
JS CODE:
$(window).scrollTop(0); // this will scroll to top of the page
LIVE DEMO:
http://jsfiddle.net/dreamweiver/fZrz7/6/
Happy Coding :)
What about $(document).scrollTop()? It always worked for me.
Try smth like this..
if($(window).scrollTop()>500){
elm.html(jdesc[id].d.substring(0,347)+'...<br><div class="readmore"><span id="'+id+'">Show More</span></div>');}
else{
elm.html(jdesc[id].d+'<br><div class="readmore"><span id="'+id+'">Show Less</span></div>');
}
If work try next with
var ofs=elm.offset().top;
Try this:
$(document).height(); //returns window height
$(document).scrollTop(); //returns scroll position from top of document
$(selector)[0].scrollHeight;
$(document).prop('scrollHeight');
Related
I am creating on an application using Objective C, where I'm using a UIWebView to display contents in HTML format. I am using below code in UIWebView delegate method webViewDidFinishLoad
NSUInteger contentHeight = [[aWebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"document.body.scrollHeight;"]] intValue];
to calculate the webview content height, this is working fine in iOS8, iOS9 and iOS11 but in iOS10 iPhone mobiles the content height returning a much bigger value than the actual content value. Because of this, I am getting some extra white space in bottom of my webview in screen.
I tried all the solutions but getting the same wrong content height only in iOS 10. Please help me to resolve this problem. Thank You in Advance!
I had used following way to get contentSize.
i have added observer(KVO) on webview's scrollview.
self.webView.scrollView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil);
Now, whenever contentsize of webview will get changed, i get callback in this method
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
}
Now take the contentSize of object from this method and use that.
Sadly, I can't track down the issue either. BUT, I think i know the culprit: html <tables> and auto-resize. There is a fair bit of discussion, in apple's safari changelog, about viewport and rendering changes, but nothing specific enough.
It would appear webviews (safari powered) render HTML differently between versions; makes sense, though i can't distill much rhyme or reason and explicit css for the <table> and <body> yielded nothing.
Hopefully, this partial answer helps make some progress or at least a work around.
I've struggled quite a lot to resize WebView correctly.
Try to add one more step before evaluating document.body.scrollHeight.
Something like this:
-(void) webViewDidFinishLoad:(UIWebView *)webView {
if[[webView stringByEvaluatingJavaScriptFromString:#"document.readyState"] isEqualToString:#"complete"]){
webViewHeight = [[WebView stringByEvaluatingJavaScriptFromString:#"document.body.offsetHeight"] floatValue];
//resize logic
}
I'm writing my code in swift and for WKWebView, but it's the same thing basically.
The point is to catch scrollHeight (or offsetHeight - couldn't figure out the difference in this case) at the right moment, and it seems that that moment is only after document.readyState.
Hope this will help you.
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
First off, I'd like to say that I'm sorry if this is an easy question. I'm fairly new to the HTML/CSS scene, and haven't even arrived at the Javascript one yet.
Here's my problem. I have a website I'm trying to build for my uncle, which you can see here. (it's still deep in pre-alpha stage, so the links don't work). It works fine as a local file, but as soon as I host it, my 'sticky' header starts to stick too soon, if at all. Reloading the page works about 1 time in 10.
I may or may not have isolated the cause of the problem: my placeholder. My sticky code itself works fine most of the time, except for one thing: as the sticky bar docks, it becomes fixed and the text jumps up 90-odd pixels. To combat this, I added lines 6 and 7 to my code below:
var sticky = document.querySelector('.sticky');
var origOffsetY = sticky.offsetTop;
function onScroll(e) {
window.scrollY >= origOffsetY ? sticky.classList.add('fixed') :
sticky.classList.remove('fixed');
window.scrollY >= origOffsetY ? jQuery('.content').css("paddingTop", "88.8125px"):
jQuery('.content').css("paddingTop", "0px");
}
document.addEventListener('scroll', onScroll);
It basically sticks a placeholder in there to stop that jump. It works fine, except now it's broken my code. I have experimented a bit and discovered that the placeholder seems to load randomly, and the header just goes weird. That's the best I can do.
It seems to be the placeholder code breaking it, as without the code it seems to work fine, perhaps after a couple of reloads. However, I am completely stumped. Has anyone got any idea how to fix it?
(Tested in Chrome 64 bit and 32 bit, as well as Chrome for Android, although that's glitchy on another level. Works fine as a local page, but not when hosted.)
It seems that the these code is executed too early that the image is not loaded yet, you can use chrome dev tool to add a pause to break to var origOffsetY = sticky.offsetTop;.
Then you can see 2 cases: 22 or 642
You can further inspect that the image, which should be the banner, is not completed when 22 condition is met, and if you use document.querySelector('.splash img') to get it and check its height, you'll see 0. While in the 642 case, you'll get 500.
The difference may be sometimes the image come from cache, sometimes it load from internet, so it may or may not able to decide the height when your script is executed.
So we have to make sure the image which is in the .splash is already loaded:
<script>
// Wrap the logic to a function for call.
var stickFunction = function() {
var sticky = document.querySelector('.sticky');
var origOffsetY = sticky.offsetTop;
function onScroll(e) {
window.scrollY >= origOffsetY ? sticky.classList.add('fixed') :
sticky.classList.remove('fixed');
window.scrollY >= origOffsetY ? jQuery('.content').css("paddingTop", "88.8125px"):
jQuery('.content').css("paddingTop", "0px");
}
document.addEventListener('scroll', onScroll);
}
// Get the image element
var splashImage = document.querySelector('.splash img');
// Check if image is complete or not.
if (splashImage.complete) { // If completed, do the logic.
stickFunction();
} else { // If not, tell the image to call the function for you when it is loaded.
splashImage.onload = stickFunction;
}
</script>
See the following fiddle:
[edit: updated fiddle => http://jsfiddle.net/NYZf8/5/ ]
http://jsfiddle.net/NYZf8/1/ (view in different screen sizes, so that ideally the image fits inside the %-width layouted div)
The image should start the animation from the position where it correctly appears after the animation is done.
I don't understand why the first call to setMargin() sets a negative margin even though the logged height for container div and img are the very same ones, that after the jqueryui show() call set the image where I would want it (from the start on). My guess is that somehow the image height is 0/undefined after all, even though it logs fine :?
js:
console.log('img: ' + $('img').height());
console.log('div: ' + $('div').height());
$('img').show('blind', 1500, setMargin);
function setMargin() {
var marginTop =
( $('img').closest('div').height() - $('img').height() ) / 2;
console.log('marginTop: ' + marginTop);
$('img').css('marginTop', marginTop + 'px');
}
setMargin();
Interesting problem...after playing around with your code for a while (latest update), I saw that the blind animation was not actually firing in my browser (I'm testing on Chrome, and maybe it was firing but I wasn't seeing it as the image was never hidden in the first place), so I tried moving it inside the binded load function:
$('img').bind('load', function() {
...
$(this).show('blind', 500);
});
Now that it was animating, it seemed to 'snap' or 'jump' after the animation was complete, and also seemed to appear with an incorrect margin. This smacks of jQuery not being able to correctly calculate the dimensions of something that hadn't been displayed on the screen yet. On top of that, blind seems to need more explicit dimensions to operate correctly. So therein lies the problem: how to calculate elements' rendered dimensions before they've actually appeared on the screen?
One way to do this is to fade in the element whose dimensions you're trying to calculate very slightly - not enough to see yet - do some calculations, then hide it again and prep it for the appearance animation. You can achieve this with jQuery using the fadeTo function:
$('img').bind('load', function() {
$(this).fadeTo(0, 0.01, function() {
// do calculations...
}
}
You would need to work out dimensions, apply them with the css() function, blind the image in and then reset the image styles back to their original states, all thanks to a blind animation that needs these dimensions explicitly. I would also recommend using classes in the css to help you manage things a little better. Here's a detailed working example: jsfiddle working example
Not the most elegant way of doing things, but it's a start. There are a lot more easier ways to achieve seemingly better results, and I guess I just want to know why you're looking to do image blinds and explicit alignment this way? It's just a lot more challenging achieving it with the code you used...anyways, hope this helps! :)
Ahoy!
I've built a little script to check the size of the left-hand margin on page load, resize a div there to fill it, and change the header div to float next to it.
Here's the code:
function buildHeader() {
var containerMarginLeft = $(".container_16:not(:first)").css("margin-left");
var headerHeight = $("#header").height();
$("#stripe").width(containerMarginLeft).height(headerHeight).css("float", "left");
$(".container_16:first").css("float", "left");
$("#header").css("margin-left", 0).width(950);
}
$(document).ready(function(){
// Manipulate layout for the first time
buildHeader();
// Manipulate layout when window is resized
var resizeTimer = null;
$(window).bind('resize', function() {
if (resizeTimer) clearTimeout(resizeTimer);
resizeTimer = setTimeout(buildHeader, 100);
});
});
And the demonstration is here: http://robertmay.me.uk/mockups/plane.html (it creates the line that stretches on the left).
Now, it works in webkit browsers. It doesn't work in Mozilla, and I've not even tried it in IE.
Anyone have any ideas as to why it doesn't seem to work in Mozilla? I have a feeling it might have something to do with the CSS.
$(".container_16:not(:first)").css("margin-left");
This line gives a result of '0px' in Firefox regardless of how wide the window gets. However, Firebug Lite in Safari shows this value as changing depending on the width of the window.
The problem seems to be with the .css('margin-left') part of the statement, since $(".container_16:not(:first)") returns the same element in both browsers. Indeed, Firebug in Firefox shows the Computed Style for this element as having '0px' for marginLeft and marginRight, but this is non-zero in Safari.
As expected, changing from 'margin-left' to 'marginLeft' makes no difference, nor does accessing the attribute directly, like $(".container_16:not(:first)")[0].style.marginLeft, because Firefox is computing it wrong in the first place.
Sorry I don't have an answer, but hopefully this will lead you in the right direction. For me though I would try to align the layout using just CSS, resorting to JavaScript fixes only as a last resort.