#85: Best Practices with Dynamic Content
One of the articles I updated during “May is Maintenance Month” was an article about dynamic content. The idea was a simple website where clicking a link would fade out the existing content and fade in new content that it fetched via AJAX. The old article didn’t encompass what I now consider to be best practices for this kind of thing. 1) Works fine with JavaScript disabled. 2) It is possible to “deep link” to specific content. 3) The browsers back button and forward button work as expected.
Links from Video:
Running Time: 31:00
Direct Download: High Quality, Quicktime .M4V Format (AppleTV Ready)
very nice working thanks
Nice work, but the vid is a bit long….
I quite like the long videos.
Would you rather a short 5 minute video that brushes over the top? The great thing about Chris’ screencasts is that they are extremely in depth.
Long == “good”
Damn! Your the man.
You’re explaining things so downright understandable. Thanks a lot.
I have a question about the differences be this screencast and the one for WordPress. The wordpress one had a lot more code. What else needs to be accounted for in AJAXing a wordpress theme that this doesn’t cover besides working for all internal links?
What do you think the problem was with the “click” issue? It seemed that whenever you would initially load the page, the About link would not work before you used the Contact link.
You had thought that maybe you were already on the About page trying to load the About page, but you were really on the Home page, so there was a problem there.
Any idea why this would be happening? Thanks!
Hey Chris,
What about putting the content of the pages in a browser based cache? Like making an array and put the requested content in the array. Then first check if the array has already got the content. Otherwise do the Ajax request. This little one helps reducing the requeste.
That would be pretty sweet. I’ve never tried to do anything like that, but I guess the concept would basically be like preloading only for HTML content. I’m sure you could speed things up that way. If you know how and want to update the demo code to do it, that would be sweet.
Sure. I’ll give it a try. I know how to do this in native JS, but i’ll look into a jQuery solution ;) Just don’t expect anything before monday, because i’m pretty busy ^^
Correction: I already made it and it’s working properly. It even loads from cache when you do a page refresh, oddly.
The result: http://lievheid.nl/DynamicPage/
Awesome! Great work. Seems to work great for me.
I think the circumstance you use this would be when you are working on a page where you think that people switching back and forth between content is going to be highly likely.
That’s also weird it pulls from cache on page reload? Seems like your code only would fill the cache array as needed. I doubt those values would persist after a page refresh. Or are browsers smart enough to hold variable values like that?
Maybe this happens because the page refresh triggers the hashchange plugin? I don’t know. I would have to investigate the issue in question. However, if that’s the case, then it isn’t all that odd, because it’s nothing different from the back button.
Since you brought up the thought of preloading the HTML, you could naturally easily do something like:
$mainContent.hide();
var preloadSafe = $guts.html();
$("nav a").each(function() {
$guts.load(newHash + " #guts", function()
{
cache[newHash] = $guts.html();
$guts.html("");
}
);
});
$guts.html(preloadSafe);
$mainContent.show();
But i doubt this is preferable on sites with large amounts of content.
Sorry for my bugger:
newHashmust be
$(this).attr('href')obviously.
That’s a swell idea as well, particularly for a site like the demo with just a few pages.
I’m addicted to your site Chris. I pretty much visit every day to learn something. Thank you very much.
Wow I am just new to js with a solid background in XHTML/CSS and this is such a clear example. Great work!
the back button in the demo on chrome doesn’t really work…but this is amazing as always
Haha funny screencast!
Really great screencast. I’ve been wondering what the deal with delegate() is for a while now, but I finally understand why it is more efficient since it only uses one event handler.
Well Other then what we were supposed to learn i had two thing stick out to me in the html. The <nav> tag and the tag are those a newer thing seems like in the past it’s always been ?
If I copy the link and go to the URL directly using the address bar, there is a problem.
Example:
If I put the address of -
http://css-tricks.com/examples/DynamicPage/about.php
and then navigate to the contact page, the URL shows up like this:
http://css-tricks.com/examples/DynamicPage/about.php#contact.php
Just a bug I thought you should be aware of.
Also, isn’t there a way to use the correct URL in the address bar instead of the hash? I could see a situation where a search engine would see the hash URL and the real URL as different pages with the exact same content.
Chris,
If the window.location.hash tag is changed to just window.location and if window.location.hash.substring(1); is changed to just window.location, the URL stays correct and everything seems to work correctly.
Is there something that I am missing? Is there a reason to use the hash tags in the URL? Just changing those two lines allows everything else to work but the URL looks the way it should.
I’ll have to try that out, but it’s my understanding that if you change the window.location value that the browser will reload the page with that location. I think it’s a security thing, like you could just change that value on page load to http://wellsfargo.com and pretend like your page is an official bank. Or am I wrong and you can change that without a refresh?
I just looked using firebug, running local (wamp), and with the demo files. Using the console, I still saw the Get requests and the URL stayed correct.
The animation of the page did stop working though.
To comment on the search engine part: Search engines don’t use JavaScript. The search enige would therefore not see any duplicate content. The point in leaving the hashlink is for users to have deep linking enabled and for search engines to have served proper content. I would however agree on the fact that if you want to refer to content with the permalink that uses this hash, you would mislead a search engine and the search engine would find no corresponding information, as where the user actually would.
The best solution to properly serve both users and search engines would be like how Chris did the site chris-mcgarry.com (See video screencast 84 for more info). Here he has all content preloaded, so search engines see all of it, and he hides what’s not being used by the user.
What I was referring to is if someone linked to test.html and someone else linked to #test.html that would be 2 separate links that are both valid. Through natural browsing, they pick up these different links. Both point to the same page and work. As far as the search engines that follow these links from different sites are concerned, they would be 2 different URLs with the exact same content.
When it comes right down to it though, I’m not sure how a search engine would interpret the hash. Will it think of it like an anchor link pointing to content that is part of a page or will it think of it as a different page. If it is content that is part of a page, it should think of it like content off of the index page. If it is a separate page, then you have the dup-content issue.
Or am I just wrong on all counts?
They wouldn’t have the same content. As i explained earlier, the search engine does not use JavaScript. Therefore if you go to #test.html, it wil actually load index.html or whatever your index page on that level is. This means we have two different links with both different content. I actually think a search engine would ignore a hash in a whole, because the default nature of a hash is to navigate to a certain area of a page, which a search engine wouldn’t need.
Chris I found a problem while using the example page: if you enter the page for the first time and you click the about link (for example) and then you click the back browser button you are not taken back to the home page…
Any solution?
This works for me when I applied it to my wordpress site, but the content fades in before the wrapper resizes – creating overflowing for a split second.
Any way to fix it?
Nevermind! I fixed it by adding overflowing: hidden to the page wrap!
Yay. Solving problems feels so satisfying.
Thank you very much for the Video!
Thanks for the great video and demo!
In Safari, in contrast to IE and Firefox, it displays the containing white box of the contact page before the page length re-sizes. You end up getting the page length doubling up and down every time you visit the contact page. How could I fix the demo so that the contact page behaves like it should in Safari?
Thanks,
Sam
Great post Chris, Thank’s for updating!
I hope you like the additional feedback i give you for your “May maintenance month”, because i do want to help you out to get the fullest out of your .
Fantastic tutorial. As always, a great help to better understanding the jQuery world and seeing some creative ways to use it. Thanks
Great screencast again Chris, you describe everything so well and it’s allowing me to be more adventurous with my coding now I’m grasping it a lot better.
I was wondering how this would be incorporated with WordPress. How would you go about bringing the content of a subpage, with what I’ve done now I get site.com/page#/subpage.
Hey great tutorial I’ve learned a lot and have applied this technique in a wordpress template I am building.
I have a slight issue though – when I click on a button , it fades out fine, but when the new page fades in, it blinks twice and it is choppy.
The link is at http://www.cameronrafati.com/test/
Do you think you can give me a suggestion on how I can fix this issue?
Thank You!
Nvm! Zacks comment already helped! thanks
Nice tut, mate!
But what about javascript in pages, which i trying to load with ajax? For example, i have div with .jScrollPane() on it. And it doesn’t work, when i attempt to load it with ajax call. Any suggestions?
Unbind the function to that interesting div of yours, load the content and then when finished, bind it once again. That should fix the issue if the function does what i think it does and that is read out the height of the inner content of the div and if needed apply a scrollbar to it. You could also solve this by deleting the whole jScrollPane and in CSS adding a
#certaindiv { overflow:auto; }where the browser will add a scrollbar if needed by default, using the css. This will also work if the content of the div changes, in realtime nonetheless.I have found another issue im having. The technique works great on FireFox but it is not workin w/ internet explorer? the site
is at http://www.cameronrafati.com/test -
Is their another component I need to add to have it work correctly on IE?
Thank you,
kenny
I took a look at your site and as you have it, you directly copied the JS from Chris. If this works in Firefox for you, i guess you modified your template to correspond to the JS, which is some interesting aproach which i will not get in to. As i see, you load a JS plugin before using the jquery library and before the DynamicPage JS. Now, i haven’t tested the JS in IE myself, so i can’t confirm anything there, but i do know that IE can be really bugging with JS. My guess is that the plugin somehow illegally, by IE standards, declared something, which let IE crash or stop running JavaScript. This would figure, because you loaded this plugin as the first JS. Moreover, Firefox, Chrome and Safari use their JS the right way and may actually not think of it as an illegal declaration.
What i found out the hard way is that when manipulating the HTML with JS, IE transforms it all to HTML4, uppercased HTML and attributes like href=”http://” are shortened to href=http://.
This could be problematic, because Chris selects the hash by means of the href attribute and if IE somehow lets jQuery interpret this as href=http://, while jQuery wants to select href=”http://”, then this actually is a bug in both jQuery and the script from Chris.
While the case where your earlier plugin in combination with IE messes things up sounds more likely to be right, i’d stick with that and try loading the page without that plugin and remake the functionality with jQuery, as you already loaded that horse of a framework.
wooo-hooo, great screencast! I’ll definitely try this for the project I’mon at the moment.
thx so much!
Thanks for this, I was doing something very similar to my website and this has really helped me. I only have one problem, I want to animate the background to a different color for each page but I can’t figure out how to do it.
Nice.
One thing I can’t figure out is how to handle Named Anchors…if possible.
I want the dynamic content a bit further down, and want to stay there when clicking. Now I end up at some mid point.
i tried to implement that one in a site and it worked, but when i put ithe page into a cms the browser doesn´t get the hashchanges. when i reload the page with the hash it works, but clicking on the links doesn´t have any effect….
what could be the problem?
Hi, is it possible to load content from the page itself (so all dynamic content to be loaded is on the same page already, just not visible until the menu item is clicked?)
Nice tutorial, however there’s 2 problems with this.
“Chris I found a problem while using the example page: if you enter the page for the first time and you click the about link (for example) and then you click the back browser button you are not taken back to the home page…”
There’s that.
And if someone with javascript on gives a link (with a hash) to a person with javascript turned of. The link wont work.
I’ve tried to come up with solutions for these problems but haven’t figured it out yet. Any ideas ?
I like this tutorial!
Thanks very much
This is awesome Chris! Now for a question:
Say your site has a lightbox effect for each image/video on the site by using a jQuery plugin –>
$("#guts a[rel^='prettyPhoto']").prettyPhoto({theme:'facebook'});When new content is loaded dynamically by clicking on the navigation link, the lightbox effect doesn’t work because the content has been added afterwards. Which would indicate that we need jQuery’s live or delegate function…but I can’t figure it out. Any thoughts?