Join 3,555 readers in helping fund MetaFilter (Hide)


Dynamic content swapping without reloading the page
March 13, 2010 6:42 PM   Subscribe

I'm building a website in which part of the page remains static, and part of the page is swapped out using server side includes. Is there a way to do this that doesn't make the page jump up to the top when a link is clicked?

The structure of the site is basically the same as my personal home page, http://www.phirephoenix.com. This is the PHP code that's doing the work:

if (isset($_GET['page'])) { $Page = $_GET['page']; }
else { $Page = 'home'; }

if (!ereg('^(list of pages on my site)$',$Page))
{ header("Location: index.php"); }
include("content/$Page.html");

If you're scrolled down part-way on the page when you click a link, you're taken back to the top of the page. My understanding is that there's an AJAX script I could incorporate into the website that would allow me to change the content within a specific div tag without reloading anything else, while maintaining your position on page. Kind of like the Facebook tabs, I guess?

Does anyone know what that script is? Alternatively, does anyone have any other suggestions for how to accomplish this?
posted by Phire to Computers & Internet (10 answers total) 5 users marked this as a favorite
 
If you use jQuery this sort of thing is very simple. Say the div's id is 'content' and the link's id is the same as the page's filename, you would do something like this:

$(document).ready(function(){
 $('.pagelink').click(function(){
  $.ajax({
   type: 'GET',
   url: 'content/' + $(this).attr('id') + '.html',
   success: function(msg){
    $('content').html(msg);
   }
  });
 )};
)};

The docs are easy to read and full of examples too.
posted by hobgadling at 6:53 PM on March 13, 2010


I know absolutely nothing about javascript, so please forgive these newbie questions:

I would include that script in the header of the page, specify the id of the link tags as the name of the page (like 'blog' or 'home' or whatever) with a blank href, and specify the id of the div tag as 'content'? Do I need to modify anything else?
posted by Phire at 7:18 PM on March 13, 2010


You would need to include jQuery first, which would look something like this:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

Then you would put the script I wrote, enclosed in javascript tags.

In addition, I see that I forgot to say that each of the links would have to have the class 'pagelink'.

After all of that, you should be good to go.
posted by hobgadling at 7:22 PM on March 13, 2010


FYI your code is sending invalid HTTP because the Location header must specify an absolute URL. Your script also has a huge security hole in that you still execute the include() on unchecked user data ($Page) even if the ereg() check returns 0. A creative user can completely own your sever with this hole by first putting php commands somewhere (such as the apache error log) and then setting $Page to something like ../../../../../../var/log/apache2/error.log\0.
posted by Rhomboid at 7:22 PM on March 13, 2010


Rhomboid: Thanks for the heads up on the location header thing! (And the security hole thing, which I've known about for a while, but my attempts to fix it based on what I find through google tend to break my page. If I get the jQuery thing to work I won't be needing server side includes anymore, but do you have any recommendations?)

Hobgadling: Right now my link tags have ID and class occupied with something else, so I'll have to play around with it a bit and report back. Thanks!
posted by Phire at 8:05 PM on March 13, 2010


The fix is not to execute the include() if ereg() returns false, i.e. add an 'else'.
posted by Rhomboid at 8:13 PM on March 13, 2010


Hobgadling: sorry I'm being such a pain about this, but it was returning an error on the last two lines, so I switched it to say }); instead of )};, but now it's telling me that this line needs an object:

"$(document).ready(function(){"
posted by Phire at 10:04 PM on March 13, 2010


A simple way to approach this might be by embedding an IFRAME in your main page to contain the changing part. So you'd have something like this in the main page:

<iframe name="content_frame" src="foo.html"></iframe>

and then your links would use a target attribute to load their href in that frame:

<a href="bar.html" target="content_frame">a link</a>
posted by Emanuel at 8:53 AM on March 14, 2010


Emanuel - I used to accomplish this with iframes, but there are a couple of drawbacks that really annoy me:

1. The size of the content stays static within the frame instead of changing with each new page.

1a. Scrolling within a scrolling window tends to be annoying for the end user.

1b. A scrollbar in the middle of your design tends to look bad - especially since Firefox isn't a big fan of letting you define the style of your scrollbars.

2. There's a lot of potential for excess code and crappy handling of on each page - in my particular case I had a background image that had to be sliced up exactly so the iframe content had the middle slice and it flowed perfectly into the larger background image of my main content page. Not hard, per se, but not elegant either. Plus with the tricky way different browsers handle CSS (I'm looking at you, Internet Explorer) there was a lot of room for error for this fix.

Plus, you can't bookmark each page. Which is a minor annoyance, but once nevertheless.
posted by Phire at 9:55 AM on March 14, 2010


jQuery may be more complicated than you need. You may be able to accomplish what you need with a simple named anchor.

Wrap the included HTML content into a DIV tag with an id.

<div id="content">[stuff]</div>

Then append #content to all of your links. the new page will reload and automatically scroll to the top of your content.
posted by device55 at 10:04 PM on March 14, 2010


« Older Looking for recommendations fo...   |  I want to wirelessly control b... Newer »
This thread is closed to new comments.