Scroll jump on page refresh with fragment - javascript

I have a page with comments. Let's call it the article page. Now, when I add a new comment, I need to reload this page since I need to see an added comment. I can't (and don't want to) inject it directly into DOM since calculating its position may be quite complex.
I'm sending an AJAX request, and in response I get:
comment id
url of the article page
Then I use it to construct URL in form myawesomewebsite.com/articlePage/{{articleId}}#{{commentId}}. So basically, I refresh current page, and additionally I add fragment part to it so that on the page load I can see my new comment.
I use
window.location = articlePageURL + "#" + commentId to construct the URL
and window.location.reload(true) to get "new" page with attached new comment
The problem is that after automatic scroll to div with comment, browser skips back to the position I was on previous page (its the same page before refreshing).
Is there any way I can turn off second page jump?

I managed to achieve what I wanted.
Instead of relying on autoscroll to id given in hash fragment of URL, i scroll to this element myself. The key is to use scrollTop css attribute on body element and combine it with animate function.
Not only it works as I expected but it gives much better UX.

Related

What happens if I use Ajax to update a single element but return entire html code in the response text?

I'm working on a website and use Ajax to update the body by id name ('mbody'). The website is working as intended but then I realized, I was returning entire page data in the responseText and updating 'mbody' with this response.
Keep in mind, the responseText does include an 'mbody' id name of its own for body.
What I don't understand is, why wasn't the website messed up? I was sticking a copy of the entire page inside an already copy of the page that's in DOM. I have since changed the Ajax update from 'mbody'.innerHTML, to an HTML tag update, since I was returning the whole page.
In case you're wondering if it's necessary to return the whole page, the answer is yes, because things change on the page from top to bottom, from screen to screen so I prefer to just return entire HTML.
So, did Ajax realize I had an 'mbody' inside the responseText and automatically just updated that part with current DOM 'mbody', or did it really place a new html page source in 'mbody' that was already in DOM?
I just want to understand the behavior of Ajax in that situation. Again, my website was perfect even when I was returning entire html source for just the body part.
// the response is returning an html page, while mbody is the current
//DOM body tag's ID
mbody.innerHTML = this.responseText;
//i later set the response to update the entire html; pseudo example
htmltag.innerHTML = this.responseText;
The website function was perfect either way, but sticking a whole page update in the body of the current, I just don't see how that didn't cause issues or destroy the layout or something.
I'm working on a website and use Ajax to update the body by id name
('mbody'). The website is working as intended but then I realized, I
was returning entire page data in the responseText and updating
'mbody' with this response.
It will be easier to debug later (and also less network traffic) if your server side code returned only the values to be updated. Using JSON could also provide less headache because it has it's own format that can easily be accessed by the Javascript without any additional work on a format protocol.
In terms of this part:
In case you're wondering if it's necessary to return the whole page,
the answer is yes, because things change on the page from top to
bottom, from screen to screen so I prefer to just return entire HTML.
You can save the "scroll y position" of the page, before the ajax call, and then after the re-rendering restore that scroll y. But none of this is necessary if you simply only change those parts of the dom that need changing, as opposed to all of it.

javascript pushState problem with redirect

I have a button on index page (index.php) that when you click it, it should take you to other page (login.php) without reloading the page simultaneously. Below is javascript with pushState.
document.getElementById('cta_btn').onclick = function() {
window.history.pushState('', '', 'login.php');
};
The problem is that I stay on same page (index.php) only url changes /login.php
pushState is a way of saying "I am using JavaScript to modify the DOM of this page so that it becomes the same as what you would get if you requested this URL". You don't appear to have written the JS to modify the DOM.
It doesn't cause new content to load by itself. It doesn't really navigate anywhere. It just pretends to so you can hook into popstate and change the DOM back to how it was before when the back button is pushed.
If you use pushState then you all need to change the DOM (with createElement and friends for simple cases and with frameworks like React for complex ones).
If you want to navigate to a new page, then assign a value to location.href.
If you don't want to load content from the server in order to do that navigation then make sure the user has previously visited the page and that caching headers were sent then.
I guess State is a Object, You should try this...
window.history.pushState({}, '', 'login.php');

Reliably jumping to named anchor on dynamically generated page?

I have a web page which is dynamically built by the client. It generates dozens of list items each with its own named anchor. The side of the page has a fixed table of contents (TOC) with hyperlinks that point to the named anchors. This allows the user to click a TOC entry a jump to the item.
The trouble I am encountering is that on the initial page load the page is dynamically generated and so it cannot scroll to the item in the initial hash of the URL using the default behavior of a browser. Additionally, when the user switches to a different book the page is completely regenerated with new content and a new starting hash. Same problem: since the hash preexists the content, it doesn't situate itself with the item already in view.
I nearly solved this with JavaScript by awaiting the rendering and then jumping to the hash using scrollIntoView method on the appropriate element.
The next problem is that the stylesheet is not fully applied by the time scrollIntoView is called and so the final position of the item is unknown. I see the unstyled item scroll into view, but once styling is applied the positioning is lost. I put a 1 second setTimeout in place to delay the scrollIntoView call. This works but feels fragile.
Are there reliable techniques for jumping to a named anchor when the content comes after the hash is in place? If I knew when the CSS was done styling content that might help. Alternately, it might be useful to trigger an event once the height of the page stabilizes (thus signaling the finalization of CSS styling).
I had a similar problem, although in my case only the table of contents and named anchors were autogenerated in the onload handler - not the rest of the page content. I solved the initial hash problem by adding the following code to my onload handler after generating the anchors:
if (location.hash)
{
var requested_hash = location.hash.slice(1);
location.hash = '';
location.hash = requested_hash;
}
I had to set the hash to '' before setting it back to the requested name to make the browser respond. This seemed to work in all the browsers I tried (Opera, Chrome, Edge, IE, FF).
You can use jQuery if you will always know the name of the element you want to set focus to. You can run this after your page has loaded:
$( "#targetElementGoesHere" ).focus();
Edit: To scroll to that, check out https://github.com/flesler/jquery.scrollTo
I think the answer you require was answered by this guy...
How to wait until a web page is loaded with javascript?
So, something like this...
document.onload = function(){
scrollIntoView...
}

Maintaining Scroll Position With Back Button and Ajax Dom Manipulation

I am loading results in with ajax with an infinite scroll, however, when you click an item in the list and navigate away from the page, then click the back button, you are back at the top of the list.
I can't figure out how to make the user return to the position they left off.
See the site I am working on:
https://www.studenthouses.com/search/manchester/
Scroll down a few times, then click a property, then click back and you will see what I mean.
I can't remember the result position and load them in because it would take too long, so really I need the browser to remember the DOM when it comes back to the page, or cache it some how.
Is there a solution to this?
Many thanks
Sure there is and it's a piece of cake. Well, it's a cookie, actually :)
You don't need much to solve this problem.
First, get some cookie here: Cookie API
Second, you'll have to encode the data in the cookie somehow. If you have multiple pages like that one, you'll have to separate them somehow or use a key-value pair and store something like this:
manchester=3522
Whenever you enter the page, load the cookie, wait the page to be fully unrolled (you use AJAX or similar, you'll have to wait for the page being unrolled, window.onload won't do).
If there is no cookie, skip this step:
scroll the page down to the offset you have loaded from the cookie: scrollTo
Next, whenever the page is scrolled, modify the cookie. To avoid thrashing you'll want to do this in a polling manner. Use setInterval() at maybe 500 milliseconds and check if the user changed the scrolling position. If he did, save the cookie with the new value.

Dynamically change iframe's content

I have an iframe tag and I want to dynamically change it using jquery animation. So for example the iframe sits on the home page, and if i click the about link, it will load the about.html and when its ready it will slide it down using animation.
I have the basic logic for it but then came about this
problem:
When I refresh the page it loads back the content of the index.html page, and what I want is that when I refresh it, it still keeps the contents of about.html.
About
<iframe id="content" name="content" align="top" src="index.html"
frameborder="0" width="100%" height="1200px" scrolling="no">
</iframe>
this is just the most basic logic, but I need help on how do I achieve the refreshing part/
and what if i dont include them in the same page but I still want to animate the page transitions. so when the users clicks a link to a new page, it will load it, and then animate it.How can I achieve this. Because recently I saw a jquery plugin callen LocalScroll and they achieve this effect, but i couldnt get it to work for new pages
Your reference to the jQuery plugin LocalScroll is on the right track. In fact, if you could implement it properly I think it would solve your problem.
Anchor-based navigation, as used in this plugin, jQuery Mobile, and other places, will update the window.location object and also be reflected in the browser's address bar so that, when an explicit page refresh occurs, the hashed location is preserved.
The answer, then, is to have a script which can parse this local link from the address. Here's a generic JavaScript code block to demonstrate this:
window.onload=function() {
var URLParts=window.location.toString().split('#');
if(URLParts.length>1)
var lastPage=decodeURI(URLParts[1]);
else
return false;
if(lastPage)
iframe_load(lastPage,'content');
}
function clear_last_page(location) {
var URLParts=location.split('#');
if(URLParts.length<=1)
return location;
URLParts.pop();
return URLParts.join('#');
}
function iframe_load(url,targetID) {
document.getElementById(targetID).src=url;
var location=clear_last_page(window.location.toString())+'#'+url;
window.location.href=location;
}
How it Works
When the window onLoad event is triggered, the URL is searched for anchor (hashed) links. If found, we will assume that this is a reference to a page and so then pass it to iframe_load().
This function does two things. First, it points your target inline frame to the page passed via url parameter. Second, it points the parent frame to a fictitious anchor, which will be preserved even after the page is refreshed.
Therefore, when you refresh the parent frame, that anchor text is grabbed, parsed, and used to re-load the last loaded inline page.
The function clear_last_page() is simply a helper function that prevents additional anchor links from being appended to the URL.
Demonstration
Visit this URL:
http://gocontactform.com/stackoverflow/dynamically-change-iframes-content/
Click the link "Page 2" to see the change. Then refresh the page.
Noteworthy
Be advised that this solution technically takes over the normal function of anchoring. So if you attempt to use anchor links normally on the page, you may get undesirable results.
You are forced to rely on iframe_load() for any links bound for that inline frame, instead of what you modeled in your question (traditional linking with a target attribute).
I might also suggest that you define no default src attribute inline. Rather, you could add to the onLoad handler a call to iframe_load('page1.html','content') and that will prevent the unnecessary attempt to load the default page when you are refreshing with anchored links in the address.
There are also other ways to accomplish what you are asking. But I believe that this solution is easy to understand and implement.
Hope that helps!
You can use the following to change the src attribute of the iFrame:
$("#content").attr('src', 'http://mysite.com/newpage.html');
Oops, looks like I misread the question.
If you want to slide it down, you can bind an event handler to the load event (jQuery doc) to do something when the frame loads.
$("#content").hide();
$("#loadLink").click(function() {
$("#content").hide();
$("#content").attr('src', 'http://mysite.com/newpage.html');
});
$("#content").load(function() {
$(this).slideDown();
});
In this example, the iframe is hidden when you click the link, and when it is ready, it slides down.
Demo
Edit: still misread it!
To save the state of which page is last shown in the iframe, you can use HTML5 localStorage.
In the load event of the iframe save the page that it's currently showing.
localStorage['lastPage'] = "about.html"
and then load it back using localStorage['lastPage'] on page load.
Updated demo showing both sliding and keeping the page after refresh.
Not possible. When you refresh a page, your browser is supposed to get the page from the server, dropping all JS data.
History API can help, but only for the newest browers.
Whenever the page loads you need to check something to know what the last src iframe loaded. By default, no browser can know this. One way to do this is to change the hash of your page when hit the click, and whenever page loads, you check if exists this hash and trigger some link with the hash.
I write this: http://jsfiddle.net/estevao_lucas/revsg/4/
Like said Michael, History API can help you.

Categories

Resources