pushState and back button works but content doesn't change - javascript

It does load a new page and the url does update, but when I press the back button, only the url has changed without refreshing but the content doesn't.
$('button').click(function(){
window.history.pushState({}, '', 'page2.php');
$('body').html('<div class="loading.gif"></div>');
//Load Page
$.get('page2.php', function(data){
$('body').html(data);
};
//Edited
$(window).bind('popstate', function(){
//What should I code here??
});
});

I did something like that :
$(window).bind('popstate', function(){
window.location.href = window.location.href;
});
And it work wonderful.
The code is taking the location from the url and redirect to this url.

I use this to change bar adress and save current state, including current html body, and i reload it on back bouton click without any other ajax call. All is saved in your browser :
$(document).ajaxComplete(function(ev, jqXHR, settings) {
var stateObj = { url: settings.url, innerhtml: document.body.innerHTML };
window.history.pushState(stateObj, settings.url, settings.url);
});
window.onpopstate = function (event) {
var currentState = history.state;
document.body.innerHTML = currentState.innerhtml;
};

You need to implement the popstate event. When you click the back button after pushing a state, the page receives the popstate event. In it you need to replace the page contents with the correct page.
See an example from MDN
Updated code:
$('button').click(function(){
// Store some information in the state being pushed
window.history.pushState({url:'page2.php'}, '', 'page2.php');
$('body').html('<div class="loading.gif"></div>');
//Load Page
$.get('page2.php', function(data){
$('body').html(data);
};
//Edited
$(window).bind('popstate', function(event){
var url = null;
if (event.state && event.state.url) {
url = event.state.url;
} else {
url = 'index.html'; // or whatever your initial url was
}
// Update the contents of the page with whatever url was stored in the state.
$.get(url, function(data){
$('body').html(data);
};
});
});

Related

ajax image viewer , back button and history - missing html and css

I am playing with jquery and js, trying to build an ajax overlay image viewer for a PHP website. With this code included at the bottom of the 'gallery page', the viewer opens and i can navigate with next and previous links inside the viewer. But the back button and the history is hard to understand. The browser often shows only the response of the ajax call, without the underlying page and css files, after some clicks back.
Perhaps somebody knows what is generally happening in such a case? I would like to understand why back sometimes results in a broken page, i.e. only the ajax response.
<script type="text/javascript">
$(document).ready(function() {
function loadOverlay(href) {
$.ajax({
url: href,
})
.done(function( data ) {
var theoverlay = $('#flvr_overlay');
theoverlay.html( data );
var zoompic = $('#zoompic');
zoompic.load(function() {
var nih = zoompic.prop('naturalHeight');
var photobox = $('#photobox');
if($(window).width() >= 750){
photobox.css('height',nih);
}
theoverlay.show();
$('body').css('overflow-y','hidden');
$(window).resize(function () {
var viewportWidth = $(window).width();
if (viewportWidth < 750) {
photobox.css('height','auto');
zoompic.removeClass('translatecenter');
}else{
photobox.css('height',nih);
zoompic.addClass('translatecenter');
}
});
});
});
return false;
}
var inithref = window.location.href;
$(window).on('popstate', function (e) {
if (e.originalEvent.state !== null) {
//load next/previous
loadOverlay(location.href);
} else {
//close overlay
$('#flvr_overlay').hide().empty();
$('body').css('overflow-y','scroll');
history.replaceState(null, inithref, inithref);
}
});
$(document).on('click', '.overlay', function () {
var href = $(this).attr('href');
history.pushState({}, href, href);
loadOverlay(href);
return false;
});
});
</script>
edit
clicking forward works:
/photos (normal page)
/photos/123 (overlay with '/photos' below)
/locations/x (normal page)
/photos/567 (overlay with '/locations/x' below)
clicking back gives me the broken view at point 2.
Do you need to prevent the default behaviour in your popstate to prevent the browser from actually navigating back to the previous page?
you have to manage it by own code.
You have a few options.
Use localstorage to remember the last query
Use cookies (but don't)
Use the hash as you tried with document.location.hash = "last search" to update the url. You would look at the hash again and if it is set then do another ajax to populate the data. If you had done localstorage then you could just cache the last ajax request.
I would go with the localstorage and the hash solution because that's what some websites do. You can also copy and paste a URL and it will just load the same query. This is pretty nice and I would say very accessible
Changing to document.location.hash = "latest search" didn't change anything.t.
This goes into the rest of the jQuery code:
// Replace the search result table on load.
if (('localStorage' in window) && window['localStorage'] !== null) {
if ('myTable' in localStorage && window.location.hash) {
$("#myTable").html(localStorage.getItem('myTable'));
}
}
// Save the search result table when leaving the page.
$(window).unload(function () {
if (('localStorage' in window) && window['localStorage'] !== null) {
var form = $("#myTable").html();
localStorage.setItem('myTable', form);
}
});
Another solution is that use INPUT fields to preserved while using back button. So, I do like that :
My page contains an input hidden like that :
Once ajax content is dynamicaly loaded, I backup content into my hidden field before displaying it:
function loadAlaxContent()
{
var xmlRequest = $.ajax({
//prepare ajax request
// ...
}).done( function(htmlData) {
// save content
$('#bfCache').val( $('#bfCache').val() + htmlData);
// display it
displayAjaxContent(htmlData);
});
}
And last thing to do is to test the hidden field value at page loading. If it contains something, that because the back button has been used, so, we just have to display it.
jQuery(document).ready(function($) {
htmlData = $('#bfCache').val();
if(htmlData)
displayAjaxContent( htmlData );
});

jQuery .load: any way to load the same page when page is refreshed

So I have a website that loads pages to a container div:
function goto(addr) {
$("#content").load(addr);
}
and a link that executes it
About us
My problem is that whenever the page is refreshed, the loaded content resets to the default page (page/home.php). How could I do so that it loads the previous displayed page?
Use local storage for example or sessions.
Local storage example:
$(document).ready(function() {
var lastPage = localStorage['lastPage'];
if (!lastPage) { // If user was on any url before we will exectue goto function
goto(lastPage)
}
function goto(addr) {
localStorage['lastPage'] = addr; // Set url to local storage before load page
$("#content").load(addr);
}
});
not only localStore but you need change the hash of url, and after do one function to catch hash code and execute at you "goto" function...
"something like that"
function hashnav(){
var hashfull = document.location.hash
var hash = hashfull.replace('#', '');
var $page = '';
goto(hash);
}
function changeHash($hash) {
window.location.hash = $hash;
}
function goto(addr) {
changeHash(addr);
}
$(window).bind( 'hashchange', function() {
hashnav();
return false;
});

Using History.js back button doesn't work?

I'm using History.js from here https://github.com/browserstate/history.js/
This is what I currently have:
var History = window.History;
if (History.enabled) {
// set initial state for first page that is loaded
var State = History.getState();
History.pushState({urlPath: window.location.pathname}, $("title").text(), State.urlPath);
}
else {
return false;
}
// content update and back/forward button handler
History.Adapter.bind(window, 'statechange', function(){
var s = History.getState();
History.log(s.data, s.title, s.url);
// update view based on load type
OnLoadPageByURL(s.data.urlPath);
});
// navigation link handler(s)
$('body').on('click', 'a', function(e){
e.preventDefault();
var load = $(e.currentTarget).data('load');
var urlPath = $(this).attr('href');
var title = $(this).text();
History.pushState({ load: load, urlPath: urlPath }, title, urlPath);
});
Everything seems to work as it should however the back button doesn't seem to work correctly? What am I doing wrong?

AJAX and setInterval for window.location.hash

//Gather AJAX links
var ajaxLink = $("#logo, .navLink, .tableLink, .footerLink");
//Mark the recent state as null (because there is none yet)
var recentState = null;
//Initialize the page state based on the URL (bookmarking compatibility)
window.onload = function() {
//If no page state exists, assume the user is at index.html
if (window.location.hash == "") {
window.location.hash = "page=index";
}
//Load the page state based on the URL
loadStateFromURL();
//Keep the page state synchronized (back/forward button compatibility)
setInterval(loadStateFromURL, 500);
//Exit
return;
}
//Use AJAX for certain links
ajaxLink.click(function() {
//Update the URL
window.location.hash = "page=" + $(this).attr("id");
//Load the page state based on the URL
loadStateFromURL();
//Return false or else page will refresh
return false;
});
//Load the page state based on the URL
function loadStateFromURL() {
//If nothing has changed, exit
if (window.location.hash == recentState) {
return;
}
//Mark the recent state
recentState = window.location.hash;
//Go through an array of all AJAX links and check their IDs
for (var i = 0; i < ajaxLink.length; i++) {
//If we find a link's ID that matches the current state, load the relevant content
if ("#page=" + ajaxLink[i].id == window.location.hash) {
//Load contents into article.main
$("article.main").fadeOut(0).load(ajaxLink[i].href, function(response, status, xhr) {
//Show an error if the request fails
if (status == "error") {
$("article.main").load("./404.html");
window.location.hash = "page=404";
}
}).fadeIn(500);
//Update the page title
document.title = "\u2622 My Website Name \u2622 " + ajaxLink[i].text;
document.getElementById("headH2").textContent = ajaxLink[i].text;
//State has been fixed, exit
return;
}
}
}
This code works flawlessly when I run it locally!!!
But when I throw it on the web server my AJAX'd links will refresh the page when I first visit. However, if I use the back button then try the link again (or I'm assuming if the page is already in the browser cache), it will work properly.
I cannot allow this, because when people first visit my page the first link they click on will not operate as intended.
One of things I've also been testing is I'll bookmark my own site with a breadcrumb bookmark (example.com/#page=14) and see if it updates without my page already being in the browser cache. Again, it works on my local machine but not on my web server.
use event.preventDefault()
ajaxLink.click(function(e) {
e.preventDefault();
//Update the URL
window.location.hash = "page=" + $(this).attr("id");
//Load the page state based on the URL
loadStateFromURL();
//Return false or else page will refresh
return false;
});
The issue maybe is that when you are applying your click event to these links, they may not be loaded to the DOM. So the possible solution is to put ajaxLink.click(function() { ... }); part inside window.load event or document.ready event. Since you have used window.load event, you can do something like this.
//Initialize the page state based on the URL (bookmarking compatibility)
window.onload = function() {
//If no page state exists, assume the user is at index.html
if (window.location.hash == "") {
window.location.hash = "page=index";
}
//Load the page state based on the URL
loadStateFromURL();
//Keep the page state synchronized (back/forward button compatibility)
setInterval(loadStateFromURL, 500);
//Use AJAX for certain links
ajaxLink.click(function() {
//Update the URL
window.location.hash = "page=" + $(this).attr("id");
//Load the page state based on the URL
loadStateFromURL();
//Return false or else page will refresh
return false;
});
//Exit
return;
}
Solved my own question, had to continuously parse the AJAX links to stay updated with the DOM as it changes.
First I put the ajaxLink declaration into a function:
//Gather AJAX links
function parseAjaxLinks() {
var ajaxLink = $("#logo, .navLink, .tableLink, .footerLink");
return ajaxLink;
}
Then I had to put the ajaxLink click events into a function:
//Load the page state from an AJAX link click event
function loadStateFromClick() {
//Update the AJAX links
var ajaxLink = parseAjaxLinks();
ajaxLink.click(function() {
//Update the URL
window.location.hash = "page=" + $(this).attr("id");
//Load the page state based on the URL
loadStateFromURL();
//Return false or else page will refresh
return false;
});
}
Then I added a line in my window.onload event to keep my AJAX click events synchronized with the DOM (this adds overhead, but oh well):
//Initialize the page state based on the URL (bookmarking compatibility)
window.onload = function() {
//If no page state exists, assume the user is at index.html
if (window.location.hash == "") {
window.location.hash = "page=index";
recentState = window.location.hash;
}
//Load the page state based on the URL
loadStateFromURL();
//Keep the page state synchronized (back/forward button compatibility)
setInterval(loadStateFromURL, 250);
//Keep AJAX links synchronized (with DOM)
setInterval(loadStateFromClick, 250);
//Exit
return;
}
If you have a keen eye, you saw I had called the new parseAjaxLinks in my new loadStateFromClick function, so I added a line to the top of my loadStateFromURL function to keep the links updated in there as well:
//Load the page state based on the URL
function loadStateFromURL() {
//Update the AJAX links
var ajaxLink = parseAjaxLinks();
...
What I learned from this is the variables which are dependent on the DOM need to be continuously updated. While the DOM is loading, things are unpredictable and kind of sucks. **Drinks beer**

AJAX loading a page without reload

I am trying to load content from a new page using AJAX. The test website I am working on is dev.dog-company.com.
This is my code:
$('a[rel="load"]').click(function(){
//var siteurl = "";
var link = $(this).attr("href");
$(this).attr("href", '#');
$('#slider-wrapper').slideUp();
$('#content').wrap('<div id="wrap"></div>').css('opacity', '0.75').css('background-color', 'black');
$.ajax({
type: 'POST',
url: link,
success : function(data){
var response = $(data);
var head= response.find('head');
var slider = response.find('#slider-wrapper');
var content = response.find('#content');
$('#content').unwrap('<div id="wrap"></div>')
jQuery("head").html(head);
if(slider != null)
jQuery("#slider-wrapper").html(slider).slideDown();
jQuery("#content").html(content);
return false;
}
$(this).attr("href", link);
})
});
I am trying load the content on click but the page reload everytime without the click working. Also I am not sure if I need to be doing something else other than what I am doing to my code. The rel="load" is only on home, info->AboutUs & FAQ.
Your help is appreciated.
Update:
I still can't get it to work. This is my latest code. And the site is still running it. When i use the debugging for chrome it never goes through my code. is it the re="load" that is causing the problem?
Update:
My initial problem was not having the document ready. But not I think the way I am parsing the information isn't working. I tried find and filter both seem to not work correctly. Also how do I change the url in the browser after I it pushes the post.
Update
After a lot of messing around with it I got it to partially work. One thing I can't do it replace head. and then the data pushed in slider is there but it does not seem to work on the website. It doesn't slide down like I have it in the code.
$('document').ready(function() {
$('a[rel="load"]').click(function(e){
//var siteurl = "";
e.preventDefault();
var link = $(this).attr("href");
$('#slider-wrapper').slideUp();
$('#content').wrap('<div id="wrap-overlay"></div>');
/*$('#wrap').css({
'opacity': '0.75',
'background-color': 'black',
'z-index' : '10'
});*/
$.ajax({
//ajax setting
type: 'POST',
url: link,
dataType: 'html',
success : function(data){
//parse data
var response = $("<div>").html(data);
console.log(typeof(response));
console.log(response);
//var head = response.find('<head>').html();
slider = response.find('#slider-wrapper').html();
var content = response.find('#content').html();
console.log(content);
//console.log(head);
//console.log(slider);
//Post data
$('#content').unwrap();
//jQuery("head").empty().append(head);
if(slider != null){
jQuery("#slider-wrapper").empty().slideDown().append(slider);
}
jQuery("#content").empty().append(content);
return false;
}
})
});
});
Try this:
$('a[rel="load"]').click(function(e) {
e.preventDefault();
// ...
});
You need to stop default browser behaviour on link click, which is following it.

Categories

Resources