jquery "empty" changes the scrollbar - javascript

i am updating content with ajax call from server.
after the update, i empty the wrapper div, that contains the data, and fill it again with the new data.
so far so good.
the problem is - that on a
$('#MessagesContainer').empty();
method - the scrollbar changes back up.
so if someione want to add data and he is in the bottom of the page, the scroll goes back up.
this action makes sense, but for this particular action i want to avoid it since it's not so "user-friendly".

you can use $('#MessagesContainer').html('');
This may work.

If the container you are emptying is almost all the content in the site that behaviour makes sense since for a millisecond the browser doesnt need a scrollbar.
Try just append a new container with the new messages and then remove the old one, in that way the user wont have any changes to the scroll state. Howere if the user was looking at something below the message container and there are more messages now than before the user might have to scroll down some.

Give you #messagecontainer a height with css. or depending on the layout add a second div with a min-height inside the scrolling div and then update the content of the inner div.

Add a height or min-height css property to the #MessagesContainer div this will mean that even when the contents are empty it still maintains a reasonable height on the page - this will keep the srollbar present

well, thanks for your answers.
use .html() would probably be better than .empty() and re-append the data.
but, the thing is that for my implementation that is not possible.
so what i did is implemented
.RemoveAfter(x) function
that remove all the elements after index 'x' in the collection and then append data from this 'x' index. that did the trick. the scrollbar stays where it is. it's not 100% percent user-friendly since it make some of the data disappear for a milisecond and then it comes back, but at this currently point, it's the best i could think of.

Related

How does jQuery Slidedown get final height of hidden item before showing it?

I'm trying to replicate jQuery slideDown() in GSAP and I'm having trouble working out how jQuery calculates the height of an item which is currently hidden as if it was set to height:auto.
I've tried trawling the code on GitHub but can't find any code which seems to be doing this in jQuery.fn.slideDown or jQuery.fn.animate which it calls.
There are several similar questions on SO and several solutions proposed, all of which seem to have their own problems:
Clone the element, position it off screen and calculate its height. This won't work if the element or any of its child elements have a height set by CSS styles which require the element to be in its original place in the DOM (e.g. an .accordianItem might only be styled if it's inside its .accordian).
Display the item, remove height:0 and quickly calculate the height before hiding the element again and then stating the animation. This might flash the content quickly while calculating the height.
Use visibility:true to show it in place while calculating the height. This would stop the flash and still keep the element in the same position in the DOM for correct height calculation, but it would still push other items below it down because visibility:false items still have a height.
Calculate the height of an item before it's hidden and store it in a data attribute so we know it when we want to open the item later. This won't work if any dynamic content changes the height of the item whilst it's hidden.
jQuery slideDown() "just works" every time so I'd be really interested to know how it works, but I just can't work out where it's doing this. I'm also surprised that GSAP can't do this out of the box, or that nobody has shared a proper solution to this before.
Any help would really be appreciated.
It turns out that if you use $.height() to get the height of an element with display:none it doesn't return 0 as you would expect, it actually sets visibility:hidden, position:absolute etc. and sets display to block to give you the correct height back. I assume this is what's being used internally when doing a slidedown.
This answer helped me a lot.
jQuery: height()/width() and "display:none"
Just to be clear about how this seems to avoid all the problems in my original question. It's basically doing number (3) but avoiding the problem of pushing lower content down the page because it's also set to position:absolute while the height is being calculated. A very simple elegant solution

Nanoscroller doesn't create a scroll if the content is inserted after the scroller is initiated

I'm using nanoscroller js to create a scrollable area in a div element. The problem is that I'm filling that div element with data with ajax (imagine facebook notifications). First there are 0 notifications, no data. Then I fill it with 10. The scrollbar isn't there. When I refresh the page (with 10 notifications now already there), it creates itself, because it knows there is more content than there is room.
How can I make it create the scroller when the data is filled?
Reinitialize the nanoScroller $("your scrollable").nanoScroller(); after you inserted the content...
like
$("your content div").append("something");
$("your scrollable container").nanoScroller();
#Jonatas Answer didn't work with me, then I figured out this one
$("#my_scrollable_container")[0].nanoscroller.reset();
I had a similar problem. My nano div originally fills the width of the screen and the amount of content does not require a scrollbar. But then a user action causes a second div to appear on the right side, making the nano div skinner and too small to display all the content -- but the scrollbar didn't appear (although I could still use the mouse wheel to scroll the nano content).
Neither of the answers provided worked for me, or maybe I applied them incorrectly. So I looked in the jquery.nanoscroller.js code (which I guess is what I should have done in the first place) and found the call is just:
$(".nano").nanoScroller();
No need to reference the div ID or anything. Each time the size of your nano div is changed, make this call and the nano scrollbar should adjust to fit. And if you have multiple nano divs in the page, this one call will reset all of them.
beware of use such a kinda :
$(".nano").nanoScroller();
cause if U have a lot of .nano DIV's and U Ajaxing data to ONE of them,
better use for example:
$("#FaceBookAjaxNotifi .nano").nanoScroller();
as Jonatas wrote..
(it boost performance dramatically in some situations)

Will the element be visible If it is added to DOM and instantly removed?

Will the element be visible even for a blink of an eye If it is added to DOM and instantly removed?
var feed = $('<div class="entry"></div>').text(data.status).appendTo(app.twitter_feed);
console.log(feed.height());
feed.remove();
I've tried the above code on a few browsers and couldn't see the element. But is this behaviour consistent through all platforms/browsers?
After reading your previous question as well, it seems that you very badly want to calculate the display height of an element before actually displaying it. I 'm not entirely clear why you want to do this (it gives off a bad smell), but here's how to anyway.
Put a <div> in your page with height: 0, overflow: hidden, and the desired width of your element¹. Add the <div> we 're talking about inside that outer helper div (it will not show no matter what), and get its height after the browser performs layout. After that you can proceed however you want (e.g. by moving the inner <div> to another position in the DOM tree).
¹ it would be best to put it exactly where you want the .entry to end up (i.e. the .entry and the helper div will end up being siblings).
PS: It's always better for everyone if you mention your real purpose.
I can imagine a situation wherein for the browser to be able to compute the element's effective height, it will have to render it on the window, or at least have the element's box reflow against the current site layout. It might not be visible (as, yeah, it's instantly removed), but a situation like this will reflow the page, and the movement of the affected elements on the page can be seen.
Images come to mind, for example, because browsers generally have no idea what the dimensions of images are until they try to lay them out (correct me if I'm wrong there though).
So, no, I wouldn't say that this is consistent behavior.
Implement it like this. Make a clone of app.twitter_feed, and send it to hell (Coordinates: x:-30000, y:-30000) and try whatever you like there.
var cloneTWFeed = $(app.twitter_feed).clone();
cloneTWFeed.css("position", "absolute").css("top","-30000").css("left","-30000");
var feed = $('<div class="entry"></div>').text(data.status).appendTo(cloneTWFeed);
console.log(feed.height());
feed.remove();
You current code works just fine, but you never get to see the element, since just after you append it, you remove it.
The browser sees it, by the time that he takes to remove it, just after being appended.
See this working Fiddle Example!
There I've replaced the console.log with an alert() to force the browser to wait for my response, thus enabling me to see the element on the page.
Note: Also works fine with console.log(), given me the 18px of height.
You either have the remove() wrapped on a timer to actually see the element (visually), or if the HTML markup is to intense, or the desired effect is to only collect data from the element, place your element inside an hidden one, that way you can remove it whenever you've done collecting data from it.
If what you must acheive is an height measurement, try to add the element without visibility (see CSS:
http://reference.sitepoint.com/css/visibility)
In a zone of the page that causes no problems on the element flow.

Insert content at top of page without scrolling

Is there a way that I can insert content at the beginning of a webpage without causing the page to give the impression of scrolling up.
I'm trying to implement something kind of like infinite scrolling but I need to be able to scroll up infinitely as well as down (I'm also unloading content on the other end so that the scroll bar doesn't become infinitesimal and the app doesn't take up too much memory).
I'm happy to use javascript, I'd rather not use a library (I'm trying to stay lighter weight than that).
Any ideas?
Before executing the code to create your element, simply do something like this:
var scrollY = window.scrollY;
window.onscroll = function(){
window.scrollTo(0, scrollY);
window.onscroll = null;
};
Keep in mind that, if you already have an onscroll function, you will need to reassign the function after this...
In my case layout was something like this:
<div class='container'>
<div class='list'>
product cards...
</div>
<button>Load more</button>
</div>
By clicking on button I want fetch data from server, dynamically create product cards with that data and add this cards to .list
Problem was that when dynamically cards added to the DOM, screen automaticaly scroll and I see only last added cards, but not first added.
I think its default behavior for all browsers (I may be wrong) - if content added in DOM above the focused element browser scroll page in order to focused element was on screen. If content added below the focused element scroll not happened and the focused element also on the screen.
To solve this problem I just add something like document.activeElement.blur() before add cards to the DOM and all was fine.
You can use window.scrollBy(x, y) to scroll down when you add content (you have to calculate the height of what you add).
One possible idea is to bypass the scroll mechanism completely and do your own.
Basically, position every element with display: fixed. You can then load elements above the screen using negative positions.
You'll have to sync the height of the document (just by adding white space) so the document scrollbars are correct. Then, you trap the scroll event and adjust the fixed positioning of all the elements within your page.
I'm not sure how smooth it will be, but I'm fairly certain you could get the effect you're looking for.
I solved it by saving the first element of the container in a variable and then after inserting I called "scrollIntoView" on it. Looks smooth to me.

Prevent "jump to Top" on jScrollPane

I am using the jScrollPane jQuery-Plugin on a -Box which is dynamically filled with content.
My problem is that on adding new content to the front of the old content, the maintainPosition option does not work. So I wrote my own code that moves the Scrollhandle back to it's original position.
The code works fine, but calling reinitialise() after adding the new content moves the handle to the top of the container just before my code reverts it's position. This results in a short flicker of the displayed content which is very disturbing.
Does anyone know a method to prevent the scroll handler to move to the top after calling "reinitialise()"?
Because noone has answered this question yet I've created a jsFiddle with my problem:
http://jsfiddle.net/hB4hE/1/
the calculation done on the second prepend link seems to solve the problem.
But if you run it StepByStep you see that the scrollbar is moved to top first.
Because I prepend many elements in my real environment this jumpy behavior is often visible.
So do you have an idea how to prevent it from jumping?
I didn't find any integrated solution to this, so I created a workaround:
1. calculate height of prepending elements
2. prepeding new elements
3. instantly scrolling down a distance equal to the height of the new prepended elements
Try using this setting: maintainPosition then you don't have to reposition yourself.
More information: http://jscrollpane.kelvinluck.com/settings.html#maintainPosition

Categories