Let's say I have a situation like this:
The page is 4000 pixels long.
The user has scrolled down the page, so 1000 pixels of content are hidden above the viewport.
Then, the user clicks a button, and content of arbitrary length is loaded via AJAX at the top of the page, pushing the button (and the content the user was looking at) below the viewport.
I've tried writing a Javascript callback to scroll down to the content the user was looking at before they clicked the button, but the experience is not seamless (a scroll "up" when new content is inserted, followed by a scroll back "down").
Is there any way to keep the viewport fixed on the content the user was looking at?
This is a simplified example, but should get the point across.
<div style="height: 1000px; width:1000px;" id="top-div">some content above the fold</div>
<button id="button">Click Me</button>
<img src="img.jpg" alt="Some image the user was looking at when they clicked the button." />
<script>
$("button").click(function() {
$.get('/new/content', function(response) {
$("#top-div").before(response);
});
});
</script>
Delay displaying the new content
The closest to an elegant solution that comes to mind is to delay displaying the new content until it's within or below the viewport. In other words, don't change the height of any major layout elements that are above the viewport; change them when they are within or below the viewport, when it won't do any harm. Display them when it's safe to do so.
For example, the user scrolls to the bottom third of a very tall page. While they're down there, some Ajax content of a new or different size is loaded near the top of the page, but it's not displayed yet. The user scrolls back up through the page, and once all of the affected layout area scrolls into view, the new content is displayed, as if it was loaded just then.
Basically, when Ajax content is loaded, retrieve the scroll position of the layout element, and either display the content or add it to a queue, based on the current scroll position of the page. Anytime the user scrolls the page or clicks on an anchor tag (or any action that changes the scroll position of the page), check the queue to see if there's any content that still needs to be displayed, and determine if it can now be safely displayed.
Make the content collapsible
Another option is to have the Ajax content appear in a collapsible format. It could be displayed initially in a small size that doesn't affect the page layout (if the layout element is above the viewport). The user can then click on the content to toggle between the collapsed format and the full version or, in a variation of the previous idea, it could automatically expand when the layout element is scrolled into view.
Check out this fiddle:
http://jsfiddle.net/FYEYB/
Here's the important code:
$("button").click(function() {
//cache the org height
var orgHeight = $("#content").height();
//run your ajax request.
mockAjax(function() {
//in the callback ajust the height
$(window).scrollTop($(window).scrollTop() + $("#content").height() - orgHeight);
});
});
Basically in the callback of your ajax request, add the difference in the height of the container to what it was before. You will probably need to add a check to make sure the new content was indeed added above the viewport, but I'll leave you to figure that out.
Related
Let's see if someone comes up with something. I have the following problem:
I need to know, with javascript or jquery, when an element has finished displaying on the screen.
It is a table that is displayed on the screen as a modal popup window. It has a main container div with the size of the entire viwport, with a z-index of 10000 and display flex so that the div that acts as a popup window is centered. What I need to know is the clientWidth and offsetWidth properties of the body of the table to determine the width of the scroll bar which is equal to offsetWidth - clientWidth, and apply this width to the right margin of another div.
When the table is finished filling in a javascript function, the d-flex class is added to the main container so that the popup modal window is displayed.
The problem is that until the popup is not physically seen on the screen it gives me that both properties are the same, that is, there is no scroll bar visible. Only when popup appears on the screen is that they are different because there is a scroll bar. The scroll bar only appears when the popup has been physically displayed on the screen.
If I ask for any visibility properties they tell me that everything is visible but it hasn't really been shown on the screen yet.
I've even tried with a jQuery extension of the show function, but it doesn't give me the results I need either.
Thank you very much for your collaboration.
Greetings
You could do a work around IF you never desire the two property values to be the same. You could implement a setInterval to keep checking the property values:
let x = setInterval(function(){
if (propertyValue1 !== propertyValue2){
clearInterval(x);
//do or trigger any code that you need to here
}
},100)
I am using .load() to refresh the contents of a div every 5 seconds.
When the div updates, the whole page will scroll back up to the top. Is there any way to prevent this from happening?
<body>
<app-header condenses reveals effects="waterfall">
<app-toolbar>
<div main-title>Title</div>
<paper-button class="custom white" raised>Log Out</paper-button>
</app-toolbar>
</app-header>
<div id="loadcards"></div>
</body>
$("#loadcards").load("getGraph.php");
$(document).ready(function(){
setInterval(function(){
$("#loadcards").load("getGraph.php");
},5000);
});
Your page scrolls back to the top when you reload because your browser very briefly does not have any content for your div. This causes the content of your page to become too small to require a scrollbar, but when the content is reapplied it might grow large enough to require a scrollbar yet again.
Option 1
You could set the Y offset to the top of your page everytime before the reload is called, then scroll back to that offset whenever the page finishes reloading (or at least as far down as possible if the page is smaller than before).
You can obtain the current offset from the top of the window with the following code:
var offsetY = $(window).scrollTop();
If you want to scroll back to where you were before, you can do so by calling the following:
$('html, body').animate({
scrollTop: $(this).offset().top
}, 300);
This will gradually scroll, but you can set 300 to 0 if you want it to scroll instantly.
Depending on the efficiency with which your page loads, you'll probably still see a jump in the page contents.
Option 2
You can alternatively put your entire DIV inside a container with a fixed height, and reload the contents inside. You should set at least a min-height on the container div.
<div style="min-height: SOME_VALUE">
<div id="loadcards"></div>
</div>
Set SOME_VALUE to whatever comes closest to your actual page size. This should prevent the page jump as well, but will cause your page to have a minimal height even when the actual contents are smaller.
Option 3
The most advanced solution would be to use a container DIV and set the height to whatever the LoadPage height is just before you reload. This way it will only reset AFTER you reload your page.
<div id="cardscontainer" style="min-height: SOME_VALUE">
<div id="loadcards"></div>
</div>
With the following changes to your JS:
setInterval(function(){
$("#loadcards").load("getGraph.php");
$('#cardscontainer').height($('#loadcards').height());
},5000);
EDIT: I swapped the 2 functions inside the SetInterval callback function because it would result in weird behaviour if the LoadCards DIV would be smaller than before.
I have a chat system on my site and defaulted the message div position to always display the last message on page load. I accomplished this by using the following line of code:
msgDiv = document.getElementById('message_row_large');
msgDiv.scrollTop = msgDiv.scrollHeight;
However, this code sets the scroll position to be equal to the div height at all times, which doesn't allow users to scroll up and see other messages.
I need to re-enable scroll to its default functionality after the page loads. ANy help is welcome.
Thank you!
P.S. I am using ajax to load chat messages. When user clicks on a name on the left hand panel, the chat between him/her and the other person loads on the right hand panel.
Try
$display = $('#message_row_large');
$display.animate({scrollTop: $display[0].scrollHeight }, 'fast');
Working Fiddle:
https://jsfiddle.net/cshanno/3bo48dxj/1/
I have a div of fixed dimensions into which some JavaScript functions will be placing text over time. When the amount of text exceeds the height of the box, a scrollbar appears thanks to overflow:scroll.
The new problem is that the view into the div stays at the same place as more content appears. What I mean to say is that it stays scrolled wherever it is as more content appears beneath, hidden unless you manually scroll down. I want to make it automatically scroll to the bottom as new content appears so that the user naturally sees what appeared most recently instead of what's oldest.
Ideas?
You can use scrollTop method after each text addition:
$("div").scrollTop($("div").children().height());
Use inner block to get the true height.
DEMO: http://jsfiddle.net/eyY5k/1/
I found this approach to work for my needs:
var realHeight = $("#history")[0].scrollHeight;
$("#history").scrollTop(realHeight);
Do note this uses jquery.
I'm wondering, is it possible to collect the height of a specific div container from a separate page with JavaScript? I'm using jQuery btw and I'm in need of comparing heights of div containers.
Edit: To clarify a bit more, I load content from a specific div in a separate page using jQuery. This content is faded into a different container with dynamic height. But in the small fraction of time before the content arrives, it shrinks down to it's min-height.
What I've done so far is collecting the height of the container before and after the load. But it only works after I've loaded content once. Because I don't have the height before it's been loaded the first time.
If the relationship between the pages is opener and [popup|child] window, then yes.
If not, you are going to run into a security wall. (unrelated pages should not have access to each other)
So, if the "other" page is a popup window that your page launched, or a child iframe that your page "launched", then yes.
I would use the jQuery .height() method to obtain the height, but how you get the object is up to you (depends on what attribute info you have etc.)
//get from popup
var otherDiv = popupWinRef.document.getElementbyId('id');
//get from iframe
var otherDiv = window.frames[frameIdOrIndex].document.getElementById('id');
alert($(otherDiv).height());
Well, you can't get it until AFTER it's loaded via jQuery. Then you need to make sure you're not having a conflict between two divs with the same ID.
From your comments it sounds like you are using ajax to load content from another page, you'll likely have the load div hidden... So I would position the loading div absolutely out of the viewport but not hidden. then get the height of your desired div but make sure you access it using the loading div and your desired div... something like this:
#divToLoadContent { position: absolute; left: -99999em; top: 0; } /* don't hide this div */
Script
var height = $('#divToLoadContent #myDesiredDiv').height();