jquery ajax navigation within ajax navigation - javascript

I'm using this code for my main site navigation which loads each page via ajax and has fallback.
$(function() {
var newHash = '',
$contentWrap = $("#content-wrap");
$("nav").on("click", "a", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).on('hashchange', function() {
newHash = window.location.hash.substring(1);
$contentWrap.load(newHash + " #content");
});
$(window).trigger('hashchange');
});​
this works fine but when i load in the content from another page for example about.html i am also loading in some more buttons for navigation within #content-wrap.
so #content-wrap now contains a data box and some more buttons for navigation. when i click on the new navigation it needs to load new data in the data box.
first i tried just pretty much copying the script above but with new anchors however i get a conflict.
i figure i need some sort of if statement, i have looked into something like if (function !== undefined) but cannot figure out what to do.
I'm not sure how well i have explained myself, i'm confused explaining it but basically i want to combine the code above with basically the same code below without a conflict.
$(function() {
var newHash = '',
$contentWrap = $("#content-wrap"),
$aboutWrap = $("#a-wrap");
$("#content-wrap").on("click", "a", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).on('hashchange', function() {
newHash = window.location.hash.substring(1);
$aboutWrap.load(newHash + " #a-content");
});
$(window).trigger('hashchange');
});​
Update: kind of works a bit but changed my plan
$(function() {
var newHash = '',
$nav = $("nav a"),
$boxBtn = '',
$aboutWrap = '',
$contentWrap = $("#content-wrap");
$("nav").on("click", "a", function() {
$(this).addClass("nav-click");
window.location.hash = $(this).attr("href");
return false;
});
$contentWrap.on("click", "a", function() {
$(this).addClass("btn-click");
window.location.hash = $(this).attr("href");
return false;
});
$(window).on('hashchange', function() {
var $aboutWrap = $("#a-wrap"),
$boxBtn = $("div.btn a");
newHash = window.location.hash.substring(1);
if ($nav.hasClass("nav-click")){
$contentWrap.load(newHash + " #content");
$nav.removeClass("nav-click");
};
if ($boxBtn.hasClass("btn-click")){
$aboutWrap.load(newHash + " #a-content");
$boxBtn.removeClass("btn-click");
};
});
$(window).trigger('hashchange');
}); /*/end*/

I had a similar problem, basically in most cases the problem is with conflicting element ID's. In the DOM you can use an ID only once. You can workaround that by using classNames and ID's for only unique elements like wrappers.

Related

Making 'scroll-sneak' work

I've been trying to make the javascript code 'scroll-sneak' (http://mrcoles.com/blog/scroll-sneak-maintain-position-between-page-loads/) work for a few weeks now. This code stops the 'page jump' (to the top) when an anchor link is clicked, and does so without disabling the functionality of that link. I'd like to have the page not move back to the top when a navigation link in a table row below is clicked. It works on the developer's demo page, but is none too well documented. Any takers for tacking this?
<tr id="tabs">
<th>Information</th>
<th>Research</th>
<th>Sources</th>
<th>Institution</th>
<th>Contact</th>
</tr>
<script>
(function() {
var sneaky = new ScrollSneak(location.hostname), tabs =
document.getElementById('tabs').getElementsByTagName('th'), i = 0, len = tabs.length;
for (; i < len; i++) {
tabs[i].onclick = sneaky.sneak;
}
document.getElementById('next').onclick = sneaky.sneak;
})();
</script>
UPDATE
In terms of my original question (and given the various problems and bugs described in the Comments below, the accepted answer proving too unpredictable in behaviour), I managed to figure out a simple solution, as below, that works in IE6, FF3, QZ6 and Webkit 537.21.
(function() {
var sneaky = new ScrollSneak(location.hostname);
document.getElementById('tabs').onclick = sneaky.sneak;
})();
One more edit:
If the last image is still giving you trouble, you can make this change and see if it helps:
Replace this:
$(active).show();
$(active).siblings().hide();
With this:
$("#gallery-interior li").hide(0, function(){
$("#gallery-interior " + active).show();
});
Previous
Here, I combined the script from the other answer and the scroll-sneak for the tabs. I tested both in FF3 and verified that they work properly, this is the complete JavaScript:
var sneaky = new ScrollSneak("scrolltrack");
$(document).ready(function() {
var urlHash = window.location.hash;
if(urlHash) {
$(".thumbs a[href='" + urlHash + "'] img").addClass("dimmed");
} else {
$(".thumbs a:first-child img").addClass("dimmed");
}
$("#tabs th a").on("click", function(e) {
sneaky.sneak();
});
$(".thumbs a").on("click", function(e) {
changeImage($(this).attr("href"), e);
});
$("#gallery-interior area").on("click", function(e) {
changeImage($(this).attr("href"), e);
});
});
function changeImage(active, e) {
var e = window.event || e;
preventNav(active, e);
$(".thumbs a img").removeClass("dimmed");
$(".thumbs a[href='" + active + "'] img").addClass("dimmed");
$(active).show();
$(active).siblings().hide();
}
function preventNav(hash, e) {
if (e) {
if (typeof e.preventDefault != 'undefined') {
e.preventDefault();
} else {
e.returnValue = false;
}
}
var node = $(hash);
node.attr("id", "");
document.location.hash = hash;
node.attr("id", hash.replace("#", ""));
}
Previous
Here you go, this script is adapted to the tabs. In the solution I posted for the gallery (Click anchor link and keep page position / prevent page-jump to top?), the page jump happens because hash links don't actually reload the page and scrolling happens by default and has to be undone. This won't have the same jumping effect for normal links, but I left the ability to capture hash links as well in case you need it. It would be best if this were placed at the bottom of the HTML of your site, just before the closing body tag.
var sneaky = new ScrollSneak("tabs", false);
var capture = true;
$(document).ready(function() {
var urlHash = window.location.hash;
$("#tabs th a").on("click", function(e) {
sneaky.sneak();
capture = true;
});
capture = false;
});
window.onscroll = function () {
if (capture) sneaky.scroll(), capture = false; // This part is only needed for hash links
};

Change div content and hash url

I made a fully functional Ajax Content Replacement script. The problem is that it adds forwards like /#about or /#work or /#contact to the adress but when I reload the site, the main page will be show. Why? How is it possible that when i type in the adress the right subpage will be show?
Someone told me that the problem is that I added the file manually when I use popstate. So I want a solution without popstate. I am not a Javascript expert but I would like to learn it. Because popstate but this is very circuitous.
window.location.hash = $(this).attr('href');
My .html files are in stored in /data/. The strange thing is that it finds the file but when I try to find it manually,the page show the main page or when I refresh the site with F5 the main page will be show,too.
Can you help me and show me how it works. We can use my code to find the error. Thanks a lot.
Here is the Websitelink : Demo Link
function refreshContent() {
var targetPage = 'home';
var hashMatch = /^#(.+)/.exec(location.hash);
// if a target page is provided in the location hash
if (hashMatch) {
targetPage = hashMatch[1];
}
$('#allcontent').load('data/' + targetPage + '.html');
}
$(document).ready(function(){
refreshContent();
window.addEventListener('hashchange', refreshContent, false);
$('.hovers').click(function() {
var page = $(this).attr('href');
$('#allcontent').fadeOut('slow', function() {
$(this).animate({ scrollTop: 0 }, 0);
$(this).hide().load('data/' + page +'.html').fadeIn('normal');
});
});
});
$('.hovers').click(function() {
window.location.hash = $(this).attr('href');
$.get('data/'+this.href, function(data) {
$('#allcontent').slideTo(data)
})
return false
})
You should load the initial page based on location.hash (if provided) on page load:
function refreshContent() {
var targetPage = 'home';
var hashMatch = /^#!\/(.+)/.exec(location.hash);
// if a target page is provided in the location hash
if (hashMatch) {
targetPage = hashMatch[1];
}
$('#allcontent').load('data/' + targetPage + '.html');
}
$(document).ready(function(){
refreshContent();
...
You can make back and forward work by listening to the Window.onhashchange event:
window.addEventListener('hashchange', refreshContent, false);
Do note that this doesn't work in Internet Explore 7 or lower.
Edit:
Okay, try this:
var $contentLinks = null;
var contentLoaded = false;
function refreshContent() {
var targetPage = 'home';
var hashMatch = /^#(.+)/.exec(location.hash);
var $content = $('#allcontent');
// if a target page is provided in the location hash
if (hashMatch) {
targetPage = hashMatch[1];
}
// remove currently active links
$contentLinks.find('.active').removeClass('active');
// find new active link
var $activeLink = $contentLinks.siblings('[href="' + targetPage + '"]').find('.navpoint');
// add active class to active link
$activeLink.addClass('active');
// update document title based on the text of the new active link
window.document.title = $activeLink.length ? $activeLink.text() + ' | Celebrate You' : 'Celebrate You';
// only perform animations are the content has loaded
if (contentLoaded) {
$content
.fadeOut('slow')
.animate({ scrollTop: 0 }, 0)
;
}
// after the content animations are done, load the content
$content.queue(function() {
$content.load('data/' + targetPage + '.html', function() {
$content.dequeue();
});
});
if (contentLoaded) {
$content.fadeIn();
}
contentLoaded = true;
}
$(document).ready(function() {
$contentLinks = $('.hovers');
refreshContent();
window.addEventListener('hashchange', refreshContent, false);
$contentLinks.click(function(e) {
e.preventDefault();
window.location.hash = '!/' + $(this).attr('href');
});
});

How to suppress JavaScript function with eg. hasClass?

I'm building on a WordPress theme and wants to load posts and pages with AJAX. I got that sorted out through the snippet below, but now I just need to suppress the function when clicking on the logo, obviously linking to the home url. So when clicking on the logo it should force a normal reload, instead of using the function.
I figure it would have something to do with "if hasClass(logo) then use default"... Yeah, I'm fairly new to JavaScript, but I have been searching a lot, so any help in the right direction will be much appreciated. Thanks!
The snippet:
$(".home li.home").removeClass("home").addClass("current_page_item");
var $wrapperAjax = $("#wrapper-ajax"),
URL = '',
siteURL = "http://" + top.location.host.toString(),
$internalLinks = $("a[href^='"+siteURL+"']"),
hash = window.location.hash,
$ajaxSpinner = $("#ajax-loader"),
$el, $allLinks = $("a");
function hashizeLinks() {
$("a[href^='"+siteURL+"']").each(function() {
$el = $(this);
if ($.browser.msie) {
$el.attr("href", "#/" + this.pathname)
.attr("rel", "internal");
} else {
$el.attr("href", "#" + this.pathname)
.attr("rel", "internal");
}
});
};
hashizeLinks();
$("a[rel='internal']").live("click", function() {
$ajaxSpinner.fadeIn();
$wrapperAjax.animate({ opacity: "0.1" });
$el = $(this);
$(".current_page_item").removeClass("current_page_item");
$allLinks.removeClass("current_link");
URL = $el.attr("href").substring(1);
URL = URL + " .entry";
$wrapperAjax.load(URL, function() {
$el.addClass("current_link").parent().addClass("current_page_item");
$ajaxSpinner.fadeOut();
$wrapperAjax.animate({ opacity: "1" });
hashizeLinks();
});
});
$("#searchform").submit(function(e) {
$ajaxSpinner.fadeIn();
$wrapperAjax.animate({ opacity: "0.1" });
$el = $(this);
$(".current_page_item").removeClass("current_page_item");
$allLinks.removeClass("current_link");
URL = "/?s=" + $("#s").val() + " .entry";
$wrapperAjax.load(URL, function() {
$ajaxSpinner.fadeOut();
$wrapperAjax.animate({ opacity: "1" });
hashizeLinks();
});
e.preventDefault();
});
if ((hash) && (hash != "#/")) {
$("a[href*='"+hash+"']").trigger("click");
}
I'm guessing you mean the script from this line: $("a[rel='internal']")
In that case, $("a[rel='internal']").not('.logo') should do the trick.
I should've read the entire code. Replace $("a[href^='"+siteURL+"']") with $("a[href^='"+siteURL+"']").not('.logo') as well.
If it has the class .logo you could add this at the top of the function:
if ($(this).hasClass('logo')) return true;
See the simple example.

jquery feature detection - how can I implement this?

I need to prevent IE from recognizing the fadeIn/Out effect in this plugin. How can I add a line of jquery feature detection code to this:
$(function() {
var newHash = "",
$mainContent = $("#main-content"),
$pageWrap = $("#page-wrap"),
baseHeight = 0,
$el;
$("nav#footer").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
$mainContent
.find("#guts")
.fadeOut(200, function() {
$mainContent.show().load(newHash + " #guts", function() {
$mainContent.fadeIn(200, function() {
});
$("nav#footer a").removeClass("current");
$("nav#footer a[href="+newHash+"]").addClass("current");
});
});
};
});
$(window).trigger('hashchange');
});
I had some code like
var FADE_TIME = 500; if(!($.support.opacity)) { FADE_TIME = 0}
$('element').fadeOut(FADE_TIME)
Where would I add this in the code? can someone help me get this working for real?please!!
Can't figure out why somebody didn't just edit the code and answer the question.
All you needed to do was create a new variable with it's value determined by the $.support.Opacity property then reference that in the fade in/out sections of the code.
$(function() {
var newHash = "",
$mainContent = $("#main-content"),
$pageWrap = $("#page-wrap"),
baseHeight = 0,
$el,
// new fadeTime property.
fadeTime = $.support.opacity ? 500 : 0;
$("nav#footer").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
$mainContent
.find("#guts")
.fadeOut(fadeTime, function() {
$mainContent.show().load(newHash + " #guts", function() {
$mainContent.fadeIn(fadeTime, function() {
});
$("nav#footer a").removeClass("current");
$("nav#footer a[href="+newHash+"]").addClass("current");
});
});
};
});
$(window).trigger('hashchange');
});
You just want to run something if the user isn't using Internet Explorer?
Try this:
if ($.browser.msie) {
return false;
} else {
//do something
}
I presume you're talking the support for the CSS opacity property and not the slightly buggy -ms-filter and filter which IE8 and below uses. In that case, the best method would be to test for the existence of the property in the style object of an element:
if('opacity' in document.createElement('div').style) {
// Do something that requires native opacity support
}
(You might want to cache the test element there if you want to test multiple properties)

setInterval with other jQuery events - Too many recursions

I'm trying to build a Javascript listener for a small page that uses AJAX to load content based on the anchor in the URL. Looking online, I found and modified a script that uses setInterval() to do this and so far it works fine. However, I have other jQuery elements in the $(document).ready() for special effects for the menus and content. If I use setInterval() no other jQuery effects work. I finagled a way to get it work by including the jQuery effects in the loop for setInterval() like so:
$(document).ready(function() {
var pageScripts = function() {
pageEffects();
pageURL();
}
window.setInterval(pageScripts, 500);
});
var currentAnchor = null;
function pageEffects() {
// Popup Menus
$(".bannerMenu").hover(function() {
$(this).find("ul.bannerSubmenu").slideDown(300).show;
}, function() {
$(this).find("ul.bannerSubmenu").slideUp(400);
});
$(".panel").hover(function() {
$(this).find(".panelContent").fadeIn(200);
}, function() {
$(this).find(".panelContent").fadeOut(300);
});
// REL Links Control
$("a[rel='_blank']").click(function() {
this.target = "_blank";
});
$("a[rel='share']").click(function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
}
function pageURL() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
$.get("loader.php", query, function(data) {
$("#load").fadeIn("fast");
$("#content").fadeOut(100).html(data).fadeIn(500);
$("#load").fadeOut("fast");
});
}
}
This works fine for a while but after a few minutes of the page being loaded, it drags to a near stop in IE and Firefox. I checked the FF Error Console and it comes back with an error "Too many Recursions." Chrome seems to not care and the page continues to run more or less normally despite the amount of time it's been open.
It would seem to me that the pageEffects() call is causing the issue with the recursion, however, any attempts to move it out of the loop breaks them and they cease to work as soon as setInterval makes it first loop.
Any help on this would be greatly appreciated!
I am guessing that the pageEffects need added to the pageURL content.
At the very least this should be more efficient and prevent duplicate handlers
$(document).ready(function() {
pageEffects($('body'));
(function(){
pageURL();
window.setTimeout(arguments.callee, 500);
})();
});
var currentAnchor = null;
function pageEffects(parent) {
// Popup Menus
parent.find(".bannerMenu").each(function() {
$(this).unbind('mouseenter mouseleave');
var proxy = {
subMenu: $(this).find("ul.bannerSubmenu"),
handlerIn: function() {
this.subMenu.slideDown(300).show();
},
handlerOut: function() {
this.subMenu.slideUp(400).hide();
}
};
$(this).hover(proxy.handlerIn, proxy.handlerOut);
});
parent.find(".panel").each(function() {
$(this).unbind('mouseenter mouseleave');
var proxy = {
content: panel.find(".panelContent"),
handlerIn: function() {
this.content.fadeIn(200).show();
},
handlerOut: function() {
this.content.slideUp(400).hide();
}
};
$(this).hover(proxy.handlerIn, proxy.handlerOut);
});
// REL Links Control
parent.find("a[rel='_blank']").each(function() {
$(this).target = "_blank";
});
parent.find("a[rel='share']").click(function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
}
function pageURL() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
var content = $("#content");
$.get("loader.php", query, function(data) {
$("#load").fadeIn("fast");
content.fadeOut(100).html(data).fadeIn(500);
$("#load").fadeOut("fast");
});
pageEffects(content);
}
}
Thanks for the suggestions. I tried a few of them and they still did not lead to the desirable effects. After some cautious testing, I found out what was happening. With jQuery (and presumably Javascript as a whole), whenever an AJAX callback is made, the elements brought in through the callback are not binded to what was originally binded in the document, they must be rebinded. You can either do this by recalling all the jQuery events on a successful callback or by using the .live() event in jQuery's library. I opted for .live() and it works like a charm now and no more recursive errors :D.
$(document).ready(function() {
// Popup Menus
$(".bannerMenu").live("hover", function(event) {
if (event.type == "mouseover") {
$(this).find("ul.bannerSubmenu").slideDown(300);
} else {
$(this).find("ul.bannerSubmenu").slideUp(400);
}
});
// Rollover Content
$(".panel").live("hover", function(event) {
if (event.type == "mouseover") {
$(this).find(".panelContent").fadeIn(200);
} else {
$(this).find(".panelContent").fadeOut(300);
}
});
// HREF Events
$("a[rel='_blank']").live("click", function(event) {
var target = $(this).attr("href");
window.open(target, "_blank");
event.preventDefault();
});
$("a[rel='share']").live("click", function(event) {
var share_url = $(this).attr("href");
window.open(share_url, "Share", "width=768, height=450");
event.preventDefault();
});
setInterval("checkAnchor()", 500);
});
var currentAnchor = null;
function checkAnchor() {
if (currentAnchor != document.location.hash) {
currentAnchor = document.location.hash;
if (!currentAnchor) {
query = "section=home";
} else {
var splits = currentAnchor.substring(1).split("&");
var section = splits[0];
delete splits[0];
var params = splits.join("&");
var query = "section=" + section + params;
}
$.get("loader.php", query, function(data) {
$("#load").fadeIn(200);
$("#content").fadeOut(200).html(data).fadeIn(200);
$("#load").fadeOut(200);
});
}
}
Anywho, the page works as intended even in IE (which I rarely check for compatibility). Hopefully, some other newb will learn from my mistakes :p.

Categories