Ajax .load refresh/back button - javascript

I'm opening part of my pages in div with Ajax. But when i refresh or hit the back button it just doesnt do what it should.
I read and tried a lot to get this to work but it just dont want to work.
I'm at a point that when i hit the the refresh or back button my address bar give the right page, but my div doenst change (e.g. address bar says: /projects.php but the page/div is still on index.php)
I just want to use the back/forward buttons and when i refresh the page it has to stay at the same page and dont go back to the first mainpage.
Here is my code, hope someone have a solution:
Html - my menu
<div id="buttons">
<a class="menu" id="page1" href="#Home">Home</a><span>|</span>
<a class="menu" id="page2" href="#Projects">Projects</a><span>|</span>
<a class="menu" id="page3" href="#About">About</a><span>|</span>
<a class="menu" href="#Contact">Contact</a>
</div>
.load part
$(document).ready(function() {
$("#page1").click(function(){
$('#content').load('index.php #content');
});
$("#page2").click(function(){
$('#content').load('projecten.php #content');
});
$("#page3").click(function(){
$('#content').load('overons.php #content');
});
});
.haschange part
$(function(){
// These two properties, set after jQuery and the hashchange event plugin are
// loaded, only need to be used when document.domain is set (to fix the "access
// denied" error in IE6/7).
$.fn.hashchange.src = '../../document-domain.html'; //--- I still dont know what to do with this, but i guess its only for IE6/7 ---//
$.fn.hashchange.domain = document.domain;
// Bind an event to window.onhashchange that, when the hash changes, gets the
// hash and adds the class "selected" to any matching nav link.
$(window).hashchange( function(){
var hash = location.hash;
// Set the page title based on the hash.
document.title = 'The hash is ' + ( hash.replace( /^#/, '' ) || 'blank' ) + '.';
// Iterate over all nav links, setting the "selected" class as-appropriate.
$('#buttons a').each(function(){
var that = $(this);
that[ that.attr( 'href' ) === hash ? 'addClass' : 'removeClass' ]( 'selected' );
});
})
// Since the event is only triggered when the hash changes, we need to trigger
// the event now, to handle the hash the page may have loaded with.
$(window).hashchange();
});

When you only change the fragment the page doesn't reload or anything.
This is the thing with SPA (Single Page Applications) - they don't reload the page. Which is why e.g. Gmail maintains the page state even though the URL after the # (aka fragment) changes. Open a different folder and/or email and see that the URL fragment changes.
You'll need to listen to those events and do actions similar to your $('#pageN').click() handlers yourself. Also do something similar if a user opens http://yourserver/#page2 directly. And think about SEO if that is applicable to you.
See a similar question: javascript - Detecting Back Button/Hash Change in URL - Stack Overflow (do try to use the HTML5 API if you can),
See e.g. Intelligent State Handling ยท browserstate/history.js Wiki for some background info.
Or create completely separate pages where the URL path (before the # changes). Like in the good old days.

Related

Link with hash : how to always navigate

On the footer of the website I'm working on, I have links to different pages, and in one case, 2 links to the same page with a different hash in the url ,like this :
<a href="http://example.com/mypage#test>Test</a>
<a href="http://example.com/mypage#test2>Test2</a>
These hashes are not true anchors, they reflect some actions the user takes (namely showing/hiding some content).
If I come from another page, I navigate without any problem. However, if I am already on "mypage", then the hash changes, but nothing happens. The browser detects and anchor change and thus tries to navigate to the anchor.
That's fair enough, but I want my user to be actually redirected to "http://example.com/mypage#test2", as if he copy-pasted it himself in the address bar. How can I achieve that ?
I could use the hashchange event but it would make it complicated to manage the rest of the javascript, so I wonder if there is a simpler way to do it.
You have a very simple solution if you are using jQuery:
$(window).on('hashchange', function() {
//code
});
Check out this: On - window.location.hash - Change?
Also this MDN documentation.
Use the location.hash property of the window object to find out what the anchor is. To detect a change in the hash, with plain javascript, just use the onhashchange event.
window.onhashchange = new function() {
window.location.replace("http://example.com/mypage" + window.location.hash);
});

Is it possible to make a link to a one page webpage to open and position itself at a specific article?

Is there a way to open a specific artical via an external link and focus on it when the links open on a one page wepage?
I have a webpage that shows content as you click on links by hiding and showing the divs. What i want is to make an external link to my webpage in the form of mywebpage/(div's name) and have the link open my page but showing the content of that div right away, instead of its usual opening content you would get when clicking on just the ordinary mywebpage link.
Is it possible? And how?
Short answer: yes.
Long answer: You will have to examine the URL's hash on page load and manually translate that into hidden or shown divs (or other positioning).
While you're at it, you could include browser history support when your divs are opened and closed.
Pulling apart what I did for http://www.tipmedia.com (Segment starts on line 322 of the page source)
//on page ready
$(document).ready(function() {
//examine hash
if(window.location.hash == "#thanks") {
//scroll to an anchor tag, slight delay to insure correct page height
setTimeout(function() {
$('html,body').animate({scrollTop:$("#contact").offset().top}, 0);
},500);
//hide and show necessary divs
$("#contactThanks").css({"display":"block"});
$("#contactIndex").css({"display":"none"});
$("#contactGeneral").css({"display":"none"});
$("#contactMeeting").css({"display":"none"});
$("#contactCareers").css({"display":"none"});
//clear the hash (not necessary for your use)
window.location.hash = "";
}
}
The history stuff is easy too, I used Modernizer.js for the best cross browser support, but it looks like this (non-Modernizer use is very similar)
//during the hide/show of new content...
//if history is available
if(Modernizr.history) {
//this data is whatever it is you wish to save
lastPageState = { div:divName, pos:amount, page:lastLoadedPage };
history.pushState(lastPageState, divName.substring(1,divName.length-6), "index.html");
}
//...
//then later, the popsate event handler
window.onpopstate = function(event) {
//examine event.state and do whatever you need to
//example segment starts line 989
//Whatever data you saved would be read here and you would do the appropriate action,
//hiding or showing divs, reloading AJAX content, etc.
}
Yes, you can use an anchor link.
So in your target page name the div with an id,say div id="target".
Then in the referring page use a link in this form
Referring Page:
GO to Target Info...
Target Page:
<div id="target">
...content...
</div>
FYI-"target" is just an example name, it could be anything...

Reload page with anchor using Javascript or Jquery

I am using anchors in my URL as a kind of variable for JavaScript, eg:
mysite.com/itempage.html#item75
This works when I click the link on any other page, but not on the actual page in question (itempage.html).
Instead of reloading the page, clicking the link simply changes the URL. Since the page does not reload, none of my JavaScript runs again.
Does anyone know a way to reload the page with the new url?
So far I have tried:
HTML
<div id="itemmenu">
<a id="item75" href="#">Item 75</a>
<a id="item11" href="#">Item 11</a>
</div>
JQUERY
$( "#itemmenu a" ).each(function(index) {
$(this).on("click", function(){
var linkid = $(this).attr('id');
var winloc = "mysite.com/itempage#" + linkid;
window.location = winloc;
});
});
This is indeed the expected behavior: not reloading the page, and simply scrolling the page to the anchor. Also, "#..." part is purely happening on client-side, and browsers don't send this part of the URI to the server, so:
http://example.com/hello.html and:
http://example.com/hello.html#toc
are considered the same URIs for the server.
If you need to reload the page, you may do something as:
<div id="itemmenu">
<a id="item75" href="?item=75">Item 75</a>
<a id="item11" href="?item=11">Item 11</a>
</div>
If you don't need to reload the page, but just to rerun JavaScript, associate required JavaScript functions with the click event on any of the concerned links.
Additional notes:
$(this).on("click", ...) can be shortened as $(this).click(...).
You don't need your actual JavaScript code: set hrefs directly in HTML code instead of changing them through JavaScript.
You could actually trigger a page reload with window.location.reload(), but I would advise against it.
Instead trigger all necessary code required for your page rendering here.
i.e.
function setupPageLayout() {
// TODO: add any code that's supposed to run on page switch
}
$(document).on('load', setupPageLayout);
$('#itemmenu a').each(function(index) {
$(this).on("click", function(){
setupPageLayout();
});
});
Links should look like:
item

Popstate with Hashtags?

I have a site that uses AJAX to dynamically load content into a div.
The links to do so are anchors with href="#" and an onclick event to trigger the AJAX.
This leaves me without a history when I click back, so if I load one page, then another and click back, it does nothing.
A basic version of the code is this:
<script type="text/javascript">
function loadXMLDoc(url)
{
<!-- Load XML Script here. -->
}
</script>
</head>
<body>
<div id="myDiv">
<!-- Target div. -->
</div>
Click Me.
Click Me.
Click Me.
</body>
What I would like to know is, can I give each link a different "#" and then use a popstate handler to call the appropriate event, so if I click link 1, 2 and then 3 and then start hitting the back button, it'll go back to 2 and then 1 etc..
I was going to use history.js and start using pushstate in the loadXML script but I think the whole manipulating history thing is a bit dirty and unreliable.
Am I thinking on the right lines or is there a better way?
Currently all my links just use "#" so that it pops back to the top of the page when loading more content but I'd like to be able to go back if possible.
Any help would be great.
Browser saves hashtags to history properly. Just add hashtag #1 to this question page, hit enter, change it to #2, hit enter, change it to #3, hit enter. Now click back button, and you'll see hash changes from #3 to #2. I recommend to change only hash itself on link click and react on page hash change and page load events.
function react() {
var hash = window.location.hash.replace("#", "");
loadXMLDoc(hash + ".txt");
};
document.body.onload = function() {
react();
window.onhashchange = react;
};
Click me
Click me
Click me
Please note that onhashchange event does not supported by old IE. The only way to deal with it if you want is to define timer with setInterval and check hashes equality.
Try to use combination of LocalStorage and HistoryAPI.
When you load XMLDoc store it in LocatStorage, when back is pressed - load data from storage, not from web.
A bit code above.
/* Handling history.back added */
window.onpopstate = function(event) {
yourHandleBackFunction(event.state);
};
function yourHandleBackFunction(renderTs) {
/*Check TS and load from localStorage if needed*/
};

Javascript: history not loading page

I have a menu that loads a new html file in a div. The loading is done by a click event attached to the menu's <a> tags. The loading works well and I add the new load to the history by constructing a new href with a hash tag.
But when I use the back button, the URL is updated correct in the browsers address field, but the page is never loaded. If I focus the address field and press enter it loads.
This is the javascript located in the mypage.html header.
<script type="text/javascript">
$(document).ready(function() {
// replace menu link click
$(".right-menu a").live('click', function(ev) {
ev.preventDefault();
ev.stopPropagation();
window.location.href = $(this).attr('href');
$("#content-right").load('mypage'+window.location.hash.substring(1)+'.html');
return false;
});
// If page loads, load the content area according to the hash.
var hrtag = window.location.hash.substring(1);
if(hrtag=="")
hrtag='about';
$("#content-right").load('mypage'+hrtag+'.html');
window.location.hash = hrtag;
});
</script>
This is the menu
<ul class="right-menu">
<li>About</li>
<li>Screens</li>
<li>License</li>
<li>Download</li>
<li>Donate</li>
</ul>
If I load the page as mypage.html, the javascript will append the hash #about and load the div id "content-right" with mypageabout.html
If I click the menu, for example download, it will load the div id "content-right" with mypagedownload.html
In both cases, the window.location will be set to the hash version of the page, mypage.html#about and mypage.html#download to register them in the history.
If i click the menu in the following order; license, about, screens and then click the browser's back button, the address field will show; mypage.html#about, mypage.html#license but it will NOT load the pages!?!
The URLs are obviously in the history, but they don't load.
Any clue to what might be wrong here?
// Thanks
EDIT - The solution
Thanks to Andres Gallo's article I came up with this solution:
<script type="text/javascript">
$(document).ready(function() {
// Make sure the page always load #about
LoadIDWithURL('#content-right','myPageAbout.html');
window.addEventListener('hashchange',function() {
if (window.location.hash != "") {
// We have a hash, use it!
LoadIDWithURL('#content-right','MyPage'+window.location.hash.substring(1)+'.html');
} else {
// We do not have a hash, force page reload!
window.history.go(0);
}
});
});
// Load the targetID with the URL loadURL.
function LoadIDWithURL(targetID,loadURL) {
$(targetID).load(loadURL);
}
</script>
I wrote a very detailed article on this exact topic. It explains how to build exactly what you are trying to do.
Furthermore my article also explains how you can pass parameters in your links to have javascript do special things
Here is a link to the article http://andresgallo.com/2012/06/08/ajaxifying-the-web-the-easy-way/
The best method is to attach your functionality to your hashchanges rather than to you click events. This allows any changes in history to take advantage of your javascript functionalities.
This is normal behaviour when navigating between pages which differ only in their hash. You have two options:
Use the hashchange event, or an emulation of it, to detect when the user changes the hash by navigation back or forward and update the page appropriately
Use the HTML5 history API.
you can try with hashchange
$(function(){
$(window).hashchange(function(){
// some event
})
})

Categories