Problem adjusting scrollbar after images have been loaded on page - javascript

Problem description: I got a page with a table containing text and thumbnails. Usually the table contains more entries than would fit on the screen leading to a scrollbar on the right side. No Problem so far. When loading the page or choosing the next page of the table (pagination) the table gets rendered - the scrollbar is at the bottom of the page where i would like it to be after complete load. Then the thumbnails are getting shown. Due to the fact that they are a bit bigger in size than the text in the table the table gets bigger in heigth leading to the scrollbar being set somewhere in the middle of the page.
Page and table after the images have been loaded, as you can see the scrollbar is somewhere in the middle (vertical) of the page:
I do not want to fiddle around with the thumbnail size. Customers are used to the actual design and image/icon sizes.
Usign the pagination function the table is the only element that gets replaced ont he page. "onload" on tables does not work unfortunatly.
What can i do to have the scrollbar appear after the images have been loaded (leading to the correct placement of the scrollbar)?
Is there a way to set the scrollbar to the bottom of the page after the table has been fully loaded?

There are jQuery plugins to wait for all images to be loaded, but I couldn't get them working on the quick, maybe you can: here and here.
However, you also could use the following hack: watch for the table height and if it changes, scroll to the bottom:
var lastHeight;
function watchTable(){
var currentHeight = $('#myTable').height();
if(currentHeight !== lastHeight){
lastHeight = currentHeight;
$('#myDiv').scrollTop(currentHeight);
}
}
setInterval(watchTable, 100);
see my demo fiddle for a working example.

The best practice is to set the widths of thumbnails in HTML or CSS, if all the thumbnails are of the same size, you can just add the style like
.thumbnail {
width: 150px;
height: 100px;
}
Or, if they size can vary, you must add width and height attributes to the ` tag.
Another solution is to:
Look at the document's scrolltop on DOMload, and look if it's at the bottom, then on onload event (which would be fired when all the images loaded) check again and if scroll to the desired position if needed.
But I recommend always set the dimensions for images, so the page wouldn't jump when they are loaded.
Edit: If you're loading images dynamically, you can do two things:
Preload images and then insert them with the right dimensions.
Use onload for images, however, you still would need to use the document.createElement('img'), so you could be sure that all the images are loaded.
Anyway, in these cases you should use something like that for each image:
var image = document.createElement('img');
image.onload = function () {
// Image is loaded
};
image.src = 'test.jpg';
Note, that you must set .src after attaching the event, or there could be some problems in Opera.

Related

How to detect when all images are loaded and elements are rendered at their appropriate heights

How can I check (with jquery or vanilla js) that all images on a page are loaded, and that they have been rendered at their final, full height, and that their parent elements have adjusted to that height?
I'm implementing a scrollspy function using jquery - something that determines where a user is on a page and highlights their position in a nav, updating their position as they scroll. In order for this to work properly, I need to know the offset.top of each section on the page I want to spy on. If I calculate the offset.top too early, before all images are loaded and displaying at their full height, the offset().top calculation will be incorrect. I want to avoid running the offset().top calculation too many times.
Things i've tried that don't fulfill my needs:
$(document).ready() and $(window).onload() are both too early, as images may not have been rendered at their full height, therefore making the sections not rendered at their full height.
the imagesLoaded library. same problem as above, doesn't account for rendering of images to their full height.
Based on my experience I think it's not trivial. window.onload may help, but it's not reliable when images are loaded dynamically. In the past I was using some kind of hack to make it workable. Basically, I was using window.setInterval and checking if image is really available by looking at property naturalWidth (see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement).
Here is an example of implementation: https://jsfiddle.net/yu8zr20h/
You are solving this issue in an incorrect way. You need to compare the current Y-value of the users window to the Y-value of all the components, or at least the containers containing the different nav values.
Imagine this is your html-code:
<div id="firstContainer">
<!-- Some content -->
</div>
<div id="secondContainer">
<!-- Some other content -->
</div>
Now you can check the height relative to the complete html page using
document.gelElementBtId('element-id').offsetTop
and the current height of the user using
scrollY
More information using this JSFiddle.
If you have image size metadata (e.g. Rails Active Storage provide it out of the box), you can write height to say dataset:
<img id="image" data-height="700" src="image.jpg" />
Then wait for it to be rendered (watch natural height):
let timer;
let image = document.getElementById("image");
function waitImage() {
if (image.naturalHeight < image.dataset.height) {
timer = setTimeout(function(){
showItems();
}, 300);
} else {
clearTimeout(timer);
useYourFullyRenderedImage();
}
}

Replacing a div id and changing css height (with overflow-y: "scroll") breaks javascript lazy load

I'm doing 2 changes on a div with jQuery:
if (jQuery("#geodir-wrapper-content").length > 0){
document.getElementById("geodir-wrapper-content").id = 'geodir_content';
}
as well as:
jQuery("#geodir_content").css({
height: "calc(100vh - "+contentHeight+"px)",
'overflow-y': "scroll",
'-webkit-overflow-scrolling': "touch"
});
The result is exactly what I want: the right shape and the right CSS classes are applied to the div.
The content within this div has images loading with lazy load javascript. The first images load fine, but when scrolling inside this div the new images don't load. They only load when the window gets resized or if there is a possibility so scroll on the main page (which I don't have on my final design).
I've set up a jsfiddle with the complete setup. Note that I can't modify the lazy load javascript as it's part of a plugin, so I'd like to find a workaround in my own code.

In HTML/JavaScript, is there a way to know an images final layout dimensions the moment the image starts loading?

I have a script that examines elements and makes all the elements equal the height of the tallest element of the set. This works fine except for when images take a while to load, because by then the heights have already been set.
To overcome this I added an onload listener to the img tag and after the image has completely loaded, it resets the height of everything correctly.
Now the problem is, if there is a particularly large image, or slow connection, things still look strange while the image is downloading. Is there a way JavaScript can know the ultimate display height of the image at the BEGINNING of the download, rather than the end?
Something like this should work.
var bigImage = new Image();
bigImage.src = "path/to/image";
bigImage.onload = function() {
//create image tag with dimensions and insert into dom
console.log(bigImage.width, bigImage.height);
}

creating a visible on load Pre-loader Page

Trying to replicate the pre-loader page on load the SVG and a background image appears and as soon as the user scrolls the page scrolls to the content and the page-loader is not visible or can be reached again unless you refresh the page, not sure how to tackle this, any help to point me in the right direction would be great- I have tried diseminating the said page.
there are a few ways to accomplish this, a simple starting point could be something like this:
basic html outline:
<div id="loader">
LOADING Image/content
</div>
<div id="body">
website body
</div>
CSS
#body{display:none;}
jQuery
$(document).ready(function(){
$("#loader").hide();
$("#body").show();
});
noscript fallback
<noscript>
<style>#loader{display:none;}#body{display:block !important;}</style>
</noscript>
Basically, this code has two divs the loader and the body, the body is set as display none in the CSS. When the page is ready, jquery is triggered to hide the loader and show the body.
The noscript fall back will set body to visible when javascript is disabled.
There are multiple ways to accomplish, this is just one idea.
Out of one of a hundred different ways, my initial thoughts were along these lines:
Wrap your main content in a wrapper with position relative and give it an offset from the top by 100% of the window width
Make the page-loader 100% height and width and position fixed
Offset the wrapper before the page is fully loaded, and then just transition it to 0 offset once the page had loaded
See a working jsfiddle here
Create an element (Div) that covers the whole screen.
Behind it (smaller z-index) add a Div container that holds all the images.
Add in JavaScript a load event function to all images:
image.onload = function() {
//image was loaded
}
Hide the cover Div when all images was loaded.
How to know when all images were loaded? add a counter or use a Promise.
Add overflow: none to disable scrolling, and add click event or scroll event (using jQuery) and set overflow to auto.
There are a lot of ways to implement each of these sections.

Issues with Fixed div on bottom of page that stops at given place

We needed a footer toolbar that stays at the bottom of the page, and sticks to some area when page is scrolled below that area.
We did achieved this using following script:
fixed div on bottom of page that stops in given place
But there is an issue on some page where the footer toolbar just disappears from the page, and then appear again when page is scrolled down further.
We found that this particular issue appears only on few page, when the page has some contents like Images, Video, or Ajax load other content where the content is filled in (or space is being filled) after page has loaded.
I have no clue how to fix this.
Here is the link from live site with problem page.
http://www.sandiegopchelp.com/services/cellphone-repair/htc/
http://www.sandiegopchelp.com/top-10-tips-to-help-secure-your-computer/
http://www.sandiegopchelp.com/notes-on-the-phablet-does-the-world-need-one/
It is usually more visible on blog posts with many comments. May be due to Disqus comments being loaded after the page has loaded completely.
How does this look?
http://jsfiddle.net/LukeGT/NxSc3/
$(window).scroll(function() {
$('#bar').css('position', 'static');
console.log($('#bar').position().top);
console.log($(window).scrollTop() + $(window).height());
if ($(window).scrollTop() + $(window).height() < $('#bar').position().top + $('#bar').height()) {
$('#bar').css('position', 'fixed');
}
});
setTimeout(function() {
$('#extra').show();
}, 1000);​
I simulated the late loading of images by just showing a few extra divs after 1 second. I believe the problem arises from the fact that the height of the page changes after the code for the bar runs, so it's behaving as it should if the page were shorter (without the images/ajax etc).
What I do instead is position the bar in it's place at the bottom of the page each time the page is scrolled, calculate its height from the top there, and compare this with the scroll height. If we're too far up, it positions the bar in a fixed position at the base of the page, and otherwise leaves it alone. It works smoothly in Chrome, but I haven't tested elsewhere.
I guess this is a problem with the $(window).height() function. Check here. For all the dynamic contents like Images, Video or Ajax-loaded content the height is not added to the result of $(window).height() unless it is specified somewhere in the HTML or CSS (and from the referred link I see this happens only in Chrome. You might want to confirm on this though). To those dynamic contents you can either try adding the height attribute in html or height attribute in the corresponding style.
This is not the answer but i have found something while inspecting your website...
This is you actual HTML when its working fine as you want..
<div class="footer-toolbar-container" id="sticky_for_a_while" style="position: fixed; ">
but when it is not working, the Position attribute is changing from Fixed to Relative .
<div class="footer-toolbar-container" id="sticky_for_a_while" style="position: relative; ">
you can check you script for that or post you script here...
At initial state, your div is in position: relative so its offset is based on the container element, not on the total height of the page. The variable stickyOffset is set based on that relative offset, that is why it gets clip down sooner than expected while scrolling and also why it works in your JSFiddle as the container there is the page (Iframe) itself.
In your $(document).ready function, you'll need to add the offset of not only the footer but also the rest of the offset on top of the containing element so that the offset is based on the total page instead of the containing div.
Hope that helps.
By looking at your example on http://www.sandiegopchelp.com/services/cellphone-repair/htc/ using chrome, I can see that your footer disappears when it gets at the "related links" section. At this moment, you set the position of the footer to "relative" so it will replace it in the regular flow of the document and its position is actually below the "related links" section which is why it disappears off screen (below "related links").
but you calculated the position at which it should become relative on page load only where you should have recalculated it after having added the "related links" section as it changes the page height (I understood that you added afterward, am I right?).
Try adding a zero height div just above the position of the sticky div, which will remain at that position as the page resizes, then check that position as you scroll to determine the position where the sticky div should stop.
Finally got it fixed by two techniques, setting explicit height wherever possible using CSS and delaying jQuery function after all images are loaded. Refer this: Delay some jQuery function until all images are loaded completely

Categories

Resources