I am trying to ajax load the center content and update the URL without changing the page. This all works fine except until I try to access the history. It seems window.pushState is not recording my URL's properly or popstate event is not working properly. I can successfully ajax load the previous page, but if I press back more than once, it stays on the same page. Any help would be greatly appreciated!
$(document).ready(function() {
$('area, .ajax_link').live('click', function(event) {
change_image(this, event);
});
window.addEventListener('popstate', function(event) {
change_image(window.location, event);
});
});
function change_image(e, event) {
if($(e).attr('target') != '_blank') {
event.preventDefault();
$.post(
base_url+'/kit/ajax_load',
{ url: this_url},
function(return_data) {
$('#content img').attr('src', return_data.image_src);
$('map').html(return_data.imagemap);
},
'json'
);
history.pushState(null, null, this_url);
update_links(this_url);
}
}
Problem Solved
#Oliver Nightingale: I needed to remove history.pushState from my change_image function. You can not call history.pushState during an onpopstate. Here is the entire working code. I shortened it above only to include the necessary parts in question. I will be adding some fallbacks next. This is tested and works in Chrome & Firefox. Tested and does not work in IE.
$(document).ready(function() {
$('area, .ajax_link').live('click', function(event) {
history.pushState(null, null, $(this).attr('href'));
change_image(this, event);
});
window.addEventListener('popstate', function(event) {
change_image(window.location, event);
});
});
function change_image(e, event) {
if(!e instanceof jQuery) {
var this_url = e;
}
else {
var this_url = $(e).attr('href');
}
if($(e).attr('target') != '_blank') {
event.preventDefault();
$.post(
base_url+'/kit/ajax_load',
{ url: this_url},
function(return_data) {
$('#content img').attr('src', return_data.image_src);
$('map').html(return_data.imagemap);
},
'json'
);
update_links(this_url);
}
}
Is the main body of change_image function happening onpopstate? If so it looks like you are pushing a new state everytime you pop a state, this could be causing some issues.
If you are using pushState for routing you could try using a library such as Davis to make things simpler.
How is $(e).attr('target') != '_blank' when e is window.location ?
As you are using the native HTML5 History API, you'll also want to have a check before history.pushState(null, null, this_url); to only call that if we are from a link.
Plus window.addEventListener('popstate', function(event) { the variable event here is actually the state's data.
See the following gists for working examples:
https://gist.github.com/balupton/1145804 - without history.js
https://github.com/browserstate/ajaxify - with history.js
Related
I'm trying to trigger an event by clicking an external link from an email using the jquery/javascript window.location.hash. Unfortunately the app is built with angular and has a hash in the url initially https://www.electricstudio.ph/#/
I even tried adding the hash manually but the functionality doesn't seem to trigger. https://www.electricstudio.ph/#/
function slideSignUp() {
$('.header-form-container.signup').addClass('active');
}
$(document).ready(function() {
if (window.location.hash == '#sign-up') {
console.log('PING');
}
});
This usually works for me:
$(window).on('hashchange', function () {
hashUrl = window.location.hash;
if (hashUrl == "#sign-up") {
console.log('PING');
}
});
I'm trying to trigger an event when the hash changes inside my url using the method onhashchange. I'm calling it, but it doesn't ever seem to get executed.
I've tried the following.
$(function () {
window.addEventListener("onhashchange", function () {
alert("Here");
});
window.onhashchange = function () {
alert("Changed");
}
)};
is there any reason why these functions aren't being called?
You should write 'hashchange' instead of 'onhashchange' in your first example.
This code works fine for me, at least in Chrome:
window.addEventListener('hashchange', function(e){
console.log('changed');
})
Here is short code-snippet:
https://jsfiddle.net/bm8jjwmq/
if ("onhashchange" in window) {
alert("The browser supports the hashchange event!");
}
▲ For Support // ▼ implementation
function locationHashChanged() {
if (location.hash === "#somecoolfeature") {
somecoolfeature();
}
}
window.onhashchange = locationHashChanged;
Source: https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onhashchange
I managed to setup a working example of using HTML5 History API. It works fine in Firefox, but in Chrome and IE11, every new press of the back or forward buttons makes page loading time much slower.
After 4 or 5 presses(going back and forth between two pages) it gets really slow.
Guess it is maybe down to on how I use AJAX to load the content, but why is it working nicely for the first few transitions between pages.
Here is a working link:
http://madebym.me/playground/AJAX-transitions/
And here is the code snippet that makes it all work:
loadContent = function () {
$.ajax({
url: pageUrl, success: function (data) {
$('#main-content').html(data);
}
});
if (pageUrl != window.location) {
window.history.pushState({ path: pageUrl }, '', pageUrl);
}
}
$(window).on('popstate', function () {
$.ajax({
url: location.pathname, success: function (data) {
$('#main-content').html(data);
}
});
});
$('a').on('click', function () {
pageUrl = $(this).attr('href');
loadContent();
return false;
});
I currently have this code:
crossroads.addRoute('/login', function(){
$.ajax({
url: '/login',
type: 'GET',
data: {
},
success: function(msg) {
$('#' + main_window).html(msg);
}
})
});
Along with this hasher.js for maintaining history:
function parseHash(newHash, oldHash){
crossroads.parse(newHash);
}
hasher.initialized.add(parseHash); //parse initial hash
hasher.changed.add(parseHash); //parse hash changes
hasher.init(); //start listening for history change
$('a').on('click', function(e) {
e.preventDefault();
hasher.setHash($(this).attr('href'));
});
Now when I have a link that says #/login and click it, the login page is loaded fine. However, if the user clicks the login link again, the page doesn't reload. I know the click is registering, but the routing/hashing isn't firing. How do I manage to do this?
Any help would be greatly appreciated. Thanks!
You are not changing anything with hasher.setHash("#/currentpage") because you are already on that page. So the change event never gets fired. You could probably just go:
$('a').on('click', function(e) {
e.preventDefault();
hasher.setHash('');
hasher.setHash($(this).attr('href'));
});
But that would clutter the history, so you could force a reload on the click, if you make the loading method available:
var loadLogin = function(){
$.ajax({
.... your ajax settings ....
});
};
crossroads.addRoute('/login', loadLogin);
$('a').on('click', function(e) {
e.preventDefault();
var newHash = $(this).attr('href');
if(newHash === '/login' && hasher.getHash() === '/login') {
loadLogin()
} else {
hasher.setHash(newHash);
}
});
EDIT
As #Patchesoft pointed out, crossroads has a property called ignoreState, which will force any request to go though the router function, even if on the current page - https://millermedeiros.github.io/crossroads.js/#crossroads-ignoreState
Your can force the call of your route by this:
// add this dummy route first
crossroads.addRoute('noop', function() { } );
$('a').on('click', function(e) {
// route to dummy route
hasher.setHash('noop');
// and then replace by your login route
hasher.replaceHash('login');
}
I'm using the following function to overload my website url links with Ajax:
$(document).ready(function() {
$('.insite').live("click", function(ev) {
if ( history.pushState ) history.pushState( {}, document.title, $(this).attr('href'));
ev.preventDefault();
$('#content').fadeOut().load($(this).attr('href')+' #content', function() {
$(this).fadeIn();
});
});
});
I would like to know if it's possible to integrate Google Analytics tracking and Disqus loading into the function.
This is the code I have tried to load disqus but it loads comments from another websites for some reasons:
window.disqus_no_style = true;
$.getScript("http://disqus.com/forums/mnml/embed.js")
Thanks
You can just put the Google Analytics function directly in the event call, placing the new virtual URL in the second parameter.
$(document).ready(function() {
$('.insite').live("click", function(ev) {
var href = $(this).attr('href');
if ( history.pushState ) history.pushState( {}, document.title, href);
ev.preventDefault();
$('#content').fadeOut().load(href+' #content', function() {
$(this).fadeIn();
_gaq.push(['_trackPageview', href ]);
});
});
});
(I've edited the function to cache the href within the event, since its inefficient to spin up 3 (now 4) separate jQuery objects for a value that will be fixed for each call. )