ready(function() doesn´t work properly - javascript

I'm using this jquery function to scroll into a div coming from a link at the index; when I execute the action (clicking on the link to go to the secondary page) and the scroll is executed, it works but not with the right 'scrollTop' measurement.
I realize that it works correctly until I reload the page. I do not know if I'm using the correct function.
var locationString = window.location.hash;
var headerHeight = -70;
$(document).ready(function(){
var divLoc = $(locationString).offset();
console.log(locationString, divLoc.top , divLoc.top + headerHeight);
$('html, body').animate({scrollTop: divLoc.top + headerHeight}, "slow");
});

The most common cause is the miss understanding of two event related to the page load: $(document).ready() (all elements of the DOM are ready to query/modify or whatever) and $(window).load() (all the images and related css are ready and the page will be rendered and will be fully displayed by the browser).
If you use $(document).ready() to apply actions that need all the page to be loaded for correctly display all the sizing, it will fail, because the images are not loaded yet so the vertical offsets (as in your case) may not be correctly computed.
So you need to use $(window).load() instead, so when you scroll to the element you will ensure that the page is fully rendered an all the elements will be placed as they should be.
Hope it helps.

Related

Scrolling to an element without ID in a window opened by window.open

At the top of my page, I have a menu with a couple of items, and when I click them, I scroll to a point of in page where the div is placed, using this line of code:
$('html, body').animate({scrollTop:$(divid).position().top - 160 }, 'slow');
where $(divid) contains the classname of the div. (I am using Drupal so the possibility of adding an ID is not there).
This works fluently, but now I have the same menu in another page. When I click a link, I navigate to the page where the div is placed in, but I can't get it to scroll to the div.
After a lot of research I came to this piece of code
$('#block-views-footer-menu-block-2 .views-row-6 a').click(function(e){
e.preventDefault();
var newwindow = window.open('/aanbod', '_self');
$(newwindow.document).ready(function(){
to_position('.field-paragraphs:nth-of-type(6)');
});
});
where to_position() contains the first line of code in this post.
However, the to_position() function fires before the new window is loaded. This way, the moment the to_position() function is fired, '.field-paragraphs:nth-of-type(6)' is not known yet, so the function cannot access the position of it.
I really don't see what I am doing wrong, any help is appreciated.
Thanks in advance!
Pass the information to the pop-up itself and let it do the scrolling for you.
var newwindow = window.open('/aanbod?scrolltoposition=' + ".field-paragraphs:nth-of-type(6)", '_self');
now in this new window, add the code to scroll the position you want to scroll to
$(document).ready( function(){
var elementSelector = location.search.split( "=" )[1];
var $element = $( elementSelector );
$('html, body').animate({scrollTop:$element.position().top - 160 }, 'slow');
} );
ensure that you have included the jquery in the pop-up
If you are using jQuery, you may use the following
$(document).ready(function(){
// your code
});
A page can't be manipulated safely until the document is "ready." jQuery detects this state of readiness for you. Code included inside $( document ).ready() will only run once the page Document Object Model (DOM) is ready for JavaScript code to execute. Code included inside $( window ).load(function() { ... }) will run once the entire page (images or iframes), not just the DOM, is ready.

Reading position indicator - Chrome issue

I'm using this code: LINK - it indicates reading position in a horizontal way.
I want to adapt this script to get not whole document height, but only one of my div's height. This is the original function:
var getMax = function(){
return $(document).height() - $(window).height();
}
I try to replace above code with this:
var getMax = function(){
var content = $("#content");
return content.height();
}
Eveything in Firefox works fine, but in Chrome my horizonal bar fills immediately. How can I fix this?
You can fix this changing your $(document).ready(fn) in $(window).load(fn) event.
ready is fired when the DOM is fully loaded, in this case your element in Chrome could not be ready or not fully loaded yet
load ,instead, assure you that all the assets in the page are loaded so you can safetly do operation on elements (in your case calculate the height).
This demo works in Firefox and Chrome.
From documentation:
The load event is sent to an element when it and all sub-elements have
been completely loaded. This event can be sent to any element
associated with a URL: images, scripts, frames, iframes, and the
window object.
Here an article that explain a little more in depth the difference between ready and load event.

jQuery .scrollTop not scrolling properly

So I've got the following code:
$(document).ready(function(){
if(window.location.hash) {
$('body,html').animate({
scrollTop: $(window.location.hash).offset().top
}, 1000);
}
})
Which I've built with the help of code taken from StackOverflow.
I call the page at url#destination so actually it should scroll to the element whose ID is the page Hash. The element exists and the page scrolls down, but not to the exact element offset, but a bit more above. It could be just fine but I want it to work as I expected.
So I now show you the console results:
>>>$("body").scrollTop()
>1155
>>>$("#aboutus").offset().top
>1672.890625
Could someone explain this to me? Because I cannot understand anything here.
Hmmm... It works fine for me. Maybe the problem is, as a user pointed in the comments, the elements haven't loaded yet so you should use $(window).load(). But if you use that, your code won't work fine since the browsers have the built-in method that when a hash exists in the url, it goes directly wherever the element whose id is the hash is. This happens because this action is triggered before the .load event detection in your javascript code. So, if you want to make sure the code works, replace the targeting of the element with other attribute like:
$(window).on("load", function(){
if(window.location.hash) {
setTimeout(function(){
$('body,html').animate({
scrollTop: $('*[idt="'+(window.location.hash).replace("#", "")+'"]').offset().top
}, 1000);
}, 130)
}
})
This should make fully sure the animation works properly, since there's no element that has got such a hash, and the js code manages the same way.
The reason it doesn't scroll to the very bottom is because your last element hasn't been added to the DOM at the time of scrollTop execution.
Make scrollTop asynchronous to wait until the DOM has completely rendered:
setTimeout(() => {
element.scrollTop = element.scrollHeight;
}, 0);

Isotope appending doesn't seem to work

I have a photo gallery powered by Isotope.Images are requested from external resource on page load and every time a user scrolls to the bottom of the page. New images are to be appended to the current isotope layout. The problem is with Isotope - it doesn't seem to execute the 'appended' method.
Searching for a solution on StackExchange and Google revealed I am not the only one having this problem. I have been tinkering with this for past couple of days and tried almost every solution I could find but so far I have not found anything that could fix my problem.
CodePen: I have created a CodePen here - http://codepen.io/Writech/pen/pBoEt
WebPage: As the custom event 'resizestop' is not working in codepen the same code is found as a webpage here - http://writech.net.ee/sandbox/
To see the problem open the CodePen or WebPage provided above and scroll to the bottom of the page which initiates loading of additional images. Then you see the new images are just appended to the container by jQuery. But they are not appended to the isotope layout instance as they are supposed to.
The problematic part lays in a custom function named isotopeAppend(). This function is called on page load and then the second part of 'if-else' statement is executed. When initialization is done and first images are added to the container then the next time isotopeAppend() is called (it's when user reaches to the bottom of the page) the first part of 'if-else' statement is executed and this is where the problematic Isotope 'appended' method is called.
A code snippet below from problematic javascript code. The results of the ajax request to external resource are applied to the variable newElems. When adding an alert('something') or console.log inside the 'appended' callback - nothing happens.
Does the problem lay in Isotope itself or does it have anything to do with my coding error?
I would really like to find a solution for this!
var elements = $(newElems).css({ opacity: 1, 'width' : columnWidthVar + 'px' });
$('#photos_section_container').append( elements );
$('#photos_section_container').imagesLoaded(function(){
$('#photos_section_container').isotope( 'appended', elements, function(){
hideLoader(function(){
elements.animate({ opacity: 1 });
});
});
});
In the initialization change
itemSelector : $('.photos_section_wrap'),
to
itemSelector : '.photos_section_wrap',
I forked your pen.
itemSelector is used by isotope to filter elements to layout and $() returns array of objects. In result there no elements to layout. If you are interested you may look at the _getAtoms method (isotope script) in debug to see what's goinig on.

Wait for jquery .html method to finish rendering

I have div with vertical scroll bar. Div is being updated dynamically via ajax and html is inserted using jQuery's .html method.
After div is updated scroll bar returns to top and I am trying to keep it in the previous position.
This is how I'm trying it:
var scrollPos = $('div#some_id').scrollTop(); //remember scroll pos
$.ajax({...
success: function(data) {
$('div#some_id').html(data.html_content); //insert html content
$('div#some_id').scrollTop(scrollPos); //restore scroll pos
}
});
This fails. My best guess is that it is failing due to inserted html not rendered (ie. no scroll).
For example this works.
setTimeout(function(){
$('div#some_id').scrollTop(scrollPos);
}, 200);
But this is dirty hack in my opinion. I have no way of knowing that some browsers won't take more then these 200ms to render inserted content.
Is there a way to wait for browser to finish rendering inserted html before continuing ?
It's still a hack, and there really is no callback available for when the HTML is actually inserted and ready, but you could check if the elements in html_content is inserted every 200ms to make sure they really are ready etc.
Check the last element in the HTML from the ajax call:
var timer = setInterval(function(){
if ($("#lastElementFromAjaxID").length) {
$('div#some_id').scrollTop(scrollPos);
clearInterval(timer);
}
}, 200);
For a more advanced option you could probably do something like this without the interval, and bind it to DOMnodeInserted, and check if the last element is inserted.
I will just like to point out one difference here: One thing, is when the .html() have completed loading, but the browser actually render the content is something different. If the loaded content is somewhat complex, like tables, divs, css styling, images, etc - the rendering will complete somewhat later than all the dom ellements are present on the page. To check if everything is there, does not mean the rendering is complete. I have been looking for an answer to this by myself, as now I use the setTimeout function.
Such callback does not exists because .html() always works synchronously
If you are waiting for images loading, there's one approach https://github.com/desandro/imagesloaded

Categories