#175
Aug 17, 2009

AJAX History and Bookmarks

Browser page history and bookmarks do not usually work with AJAX requests, but in this episode I show you how to remedy this problem using a simple jQuery plugin.
Tags: ajax plugins
Download (20.7 MB, 11:04)
alternative download for iPod & Apple TV (13.1 MB, 11:04)

Resources

$(function() {
  $(".pagination a").live("click", function() {
    $.setFragment({ "page" : $.queryString(this.href).page })
    $(".pagination").html("Page is loading...");
    return false;
  });
  
  $.fragmentChange(true);
  $(document).bind("fragmentChange.page", function() {
    $.getScript($.queryString(document.location.href, { "page" : $.fragment().page }));
  });
  
  if ($.fragment().page) {
    $(document).trigger("fragmentChange.page");
  }
});

RSS Feed for Episode Comments 40 comments

1. Seth Crosby Aug 17, 2009 at 00:07

Looks great, thanks. Do you use jquery to the exclusion of protoype now?
sc


2. xinuc Aug 17, 2009 at 01:13

You're my hero :D


3. Ahmed Al Hafoudh Aug 17, 2009 at 01:32

great screencast again! very clean solution. briliant!


4. vesters Aug 17, 2009 at 03:14

As always very cool!

One question you or others may know the answer to:

Is it possible to let tools like 'Google analytics' to pick up on the traffic the pages get, when it's all done in JS?


5. PanosJee Aug 17, 2009 at 04:41

@vesters yes it is
search for "track javascript events google analytics" you can even track flash events


6. RedmarKerkhoff Aug 17, 2009 at 05:57

@vesters it's something like: 'pageTracker._trackPageview('/pageNameHere');' pageNameHere can be nested with slashes and can be any identifier/label you want.


7. Stewart Johnson Aug 17, 2009 at 06:14

Phew! I just finished watching all 175 episodes (took me a couple of weeks) and now I'm up to speed. Ryan, it's fantastic that you make such a terrific resource available to us for free -- it's much appreciated!


8. Fredd Aug 17, 2009 at 07:47

The question now is.. Should I migrate from prototype to jquery? jquery shows a lot of progress these days but the ajax helpers in Rails are for prototype:(


9. Millisami Aug 17, 2009 at 08:08

Firstly, thanks Ryan for the part-2.

@Fredd, you could use jRails to make the helpers work with jquery seamlessly.


10. Jeff Tucker Aug 17, 2009 at 10:20

Thanks for a useful series Ryan. One question though: why not rewrite the URL to just include the query string rather than a fragment? It seems that would eliminate the need to have an event listener for refresh/bookmarking.


11. Ryan Bates Aug 17, 2009 at 10:34

@Seth, I do primarily use jQuery, but sometimes I will still use Prototype depending on what I'm doing.

@Fredd, I think it's good to learn both libraries and see which you feel most comfortable with. As Millisami mentioned you can use jRails to add helper methods for jQuery, but I prefer to stick with the unobtrusive approach in jQuery.

Also, the javascript helpers in Rails 3 will be unobtrusive and library agnostic (so it will work with jQuery).

@Jeff, IIRC changing the url through javascript triggers a page reload, so that is why you can only change the fragment.


12. Bryce Aug 17, 2009 at 12:00

Ryan, thanks for another great screencast. Although not specifically about ruby or rails, javascript is certainly something we all do and could get better at.

Your solution in jQuery is great; really simple and extremely readable.

For the both of us that use Mootools, this looks like a good solution that will follow the same principles described in this screencast.

http://digitarald.de/project/history-manager/


13. ALLCAPS Aug 17, 2009 at 12:51

Incredible episode, thanks!


14. Murdoch Aug 17, 2009 at 15:06

The last episodes were instrumental for me in somewhat abstracting the episode code to put ajax requests on all links between an .ajax_frame tag without explicitly specifying the params to pass:

http://pastie.org/586433

Or are there any problems with it resp. cases where ajax links are not working? :-)


15. Goldy Aug 17, 2009 at 19:08

Ryan, here's a scenario that is be a bit ugly.

Say someone opens page 2 in a new window, thus having the url:

/products?page=2

Then if they click on the page 3 link they have the url

/products?page=2#page=3

Ewwww. In this case the likelihood of this happening is low, but in my app it's pretty likely.

Any ideas to avoid this?


16. Nils Ivanson Aug 18, 2009 at 03:57

The following scenario concerns me.

Person A has JavaScript enabled.
Person B has JavaScript disabled.

A browses the pagination and tells B to enter the same url.

B will end up on the first page with no notice.

The controller must be modified to redirect #page=x to ?page=x before loading the page. Right?


17. Ryan Bates Aug 18, 2009 at 07:15

@Murdoch, nice abstract solution. I think the full URL in the hash is a little ugly, but the simplicity is great. Also you should remove the jQuery.get call on line 3.

@Goldy, unfortunately I don't know of a good way to avoid the double page params. You could use javascript to remove the "?page=2" portion but that will cause a page reload.

@Nils, the fragment (#page=x) does not get sent to the server, so there's no way we could parse it in the controller. I don't know of a solution here unfortunately.


18. Stan Kaufman Aug 18, 2009 at 09:28

Guess I'm an aging Luddite, but what is the advantage of using AJAX here? All the important page content is reloaded by a trip to the server anyway, and you have to manually (well, using the utils plugin) handle all the page history stuff that ordinary page requests do automatically. What does this relatively complicated alternative win you?


19. Maz Aug 18, 2009 at 14:09

You could use a dynamically generated script tag to get the pagination data. This is cleaner in IE where using XmlHTTPRequest triggers an Active-X warning.


20. Goldy Aug 18, 2009 at 18:16

Hi Ryan,
Thanks so much for your reply. I must say it's quite an ego boost for me knowing that your thinking matched mine :) Many thanks for your screencasts and your work on rails in general.

@Stan - I think this is a very cool technique - I consider pagination just an example. (Indeed I'm not using it as such.) Just look at what gmail achieves with it.


21. Memiux Aug 18, 2009 at 21:29

I love all your episodes, I can't describe the quality of them with words, thank you!


22. Andrew Vit Aug 20, 2009 at 14:13

@18: You're right that the example in this episode doesn't make much sense for Ajax. You also lose the benefit of client-side caching since every click of the back button is a new request... but the technique is helpful when there are other things on the page that you can't afford to reload: think of the pagination on YouTube comments for example.


23. Max Aug 22, 2009 at 01:41

Yeah! Thanks i have been waiting for this screencast since i saw previous screencast about AJAX pagination...

Thank you!


24. natash Aug 22, 2009 at 06:59

Awesome! You solve my problem. Thank You !!!


25. Waqas Aug 22, 2009 at 21:48

Once again very usefull screencast. I have implemented it in my new rails website. Having few problems but I will get in fully working.


26. Vagmi Mudumbai Aug 23, 2009 at 08:24

You must really checkout Sammy (http://code.quirkey.com/sammy). Sammy gives all of this and much more. It can be used alongside this plugin too.


27. Joe Aug 26, 2009 at 03:52

Thanks for this awesome Railscast Ryan! One small question remains: I'd like to set the fragment to a certain string like '#/action/subaction'. Any ideas how to manage this without having some key-value pair in my url?
Thanks and greetings,
Joe


28. Sig Aug 30, 2009 at 08:43

Hello Ryan (and guys),
instead having
/#page=2
/#page=3
I'm trying to have
/#projects
/#tasks

Basically I'm trying to filter my elements by keyword, but I have hard time to achieve so

Is there a way to create such a URL?

Thanks


29. helloworlder Sep 22, 2009 at 05:10

Awesome! I almost gave up doing AJAX based pagination then this comes out!


30. chris Sep 25, 2009 at 13:27

How did your get to know so much?


31. jack Sep 26, 2009 at 23:45

I turned off Javascript and the site still works without the AJAX pagination. So I guess this is unobtrusive and SEO friendly too.


32. "Cowboy" Ben Alman Oct 15, 2009 at 05:07

I'm fairly positive that this comment will get lost amidst all the spam, but I just want to mention that these two new plugins: jQuery BBQ and jQuery urlInternal supersede URL Utils. I've refined and simplified the hash / history API significantly, and separated the functionality into two logical, complimentary plugins:

jQuery BBQ:
http://benalman.com/projects/jquery-bbq-plugin/

jQuery urlInternal:
http://benalman.com/projects/jquery-urlinternal-plugin/

Check them out if you haven't already!


33. Olyusya Feb 20, 2010 at 08:30

I'm fairly positive that this comment will get lost ...


34. Kevin Ansfield Apr 06, 2010 at 15:53

The URL Utils example described in the screencast seems so much simpler than attempting to implement similar features using the jQuery BBQ and jQuery urlInternal plugins - am I missing something or has this project taken a step backwards?


35. ewall Apr 06, 2010 at 19:35

Kevin--

It took me a little bit to wrap my mind around the changes in Ben Alman's JavaScript, but in the end it turns out to be similar in length and complexity.

Here's a clean interpretation of the pagination.js using jQuery-BBQ: http://gist.github.com/358429


36. chanel May 26, 2010 at 01:01

asdfasdfsdffsd


37. Azohba Jun 19, 2010 at 05:04

Tebrikler arkadaşlar


38. discount nfl jerseys Jun 23, 2010 at 00:47

www.donejerseys.com
http://www.donejerseys.com/nfl-jerseys-c-1.html


39. permatec Jun 24, 2010 at 08:55

Great.I like it!


40. webtasarim Jul 15, 2010 at 09:05

web tasarımı, kurumsal site tasarımı, profesyonel web sitesi tasarımı, profesyonel web tasarımı

<a href="http://www.webtasarimturk.net" title="web tasarımı">web tasarımı</a>


41. seas Jul 30, 2010 at 22:24

I agree with you, but I also have a few comments.


42. bamboo-kitchen Jul 30, 2010 at 22:30

Well, I have the following comments,


43. David Aug 01, 2010 at 07:29

thanks for the post. I'm using the new BBQ library and that's also very easy to use.


47. logo design Aug 08, 2010 at 23:46

Can i use jquery to the exclusion of protoype now?


48. education diplomas Aug 12, 2010 at 00:47

@Nils, the fragment (#page=x) does not get sent to the server, so there's no way we could parse it in the controller. I don't know of a solution here unfortunately.


49. Affordable Logo Design Aug 14, 2010 at 06:41

I switched off Javascript and my website still working without AJAX pagination.I think it is unnoticeable and SEO friendly as well.


50. 传奇私服 Aug 15, 2010 at 04:01

  Finally, got what I was looking for!! I definitely enjoying every little bit of it. Glad I stumbled into this article! smile I have you bookmarked to check out new stuff you post


51. online health sciences certificates Aug 15, 2010 at 22:39

Is it possible to let tools like 'Google analytics' to pick up on the traffic the pages get, when it's all done in JS?


52. UGG Classic Argyle Knit Aug 16, 2010 at 02:06

  The perfect!These articles written too great,they rich contents and data accurately.they are help to me.I expect to see your new share


53. nike dunks low Aug 19, 2010 at 22:47

Such a great blog post. I would have liked to have seen the content partial. thanks for this information.


54. Wholesale baseball hats Aug 20, 2010 at 20:26

It's funny how we adopt words and adapt our lexicon to the times. This is a very useful slant on things.


55. PDF to Images Converter Aug 24, 2010 at 23:14

Some times, to a certain need, we have to convert PDF to image for enjoyment.


56. Wholesale Electronics Aug 25, 2010 at 01:42

Discount Wholesale Electronics, Wholesale Cell Phones, Electronic Gadgets and More from the Best Dropship Wholesaler


57. jordan 6 rings Aug 25, 2010 at 04:14

are you


58. louis vuitton shoes Aug 26, 2010 at 21:10

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


59. Benjamin "balupton" Lupton Aug 28, 2010 at 10:29

Other fantastic alternatives include jQuery History which provides nice tracking of hash changes for your website. And jQuery Ajaxy which allows you to have a rich ajax website while still supporting the back and forward buttons and no server side changes.
jQuery History: http://www.balupton.com/projects/jquery-history
jQuery Ajaxy: http://www.balupton.com/projects/jquery-ajaxy


60. Cable Accessories Aug 30, 2010 at 20:28

it is a nice post, i get a lot of useful information, thanks for your sharing.


61. dallas cowboys jerseys Aug 30, 2010 at 20:29

Thanks for posting this. <a href="http://www.nflcowboysjerseys.com/marion-barber-jerseys-c-1_18.html">Marion Barber Jerseys</a> Very nice recap of some of the key points in my talk. I hope you and your readers find it useful! Thanks again
http://www.nflcowboysjerseys.com/cowboys-jerseys-c-1.html Cowboys Jersey


62. snow boots Aug 30, 2010 at 20:50

For the both of us that use Mootools, this looks like a good solution that will follow the same principles described in this screencast.


63. louis vuitton sunglasses Sep 01, 2010 at 22:41

Hi, good post, and awesome weblog you have here!
What’s this theme you use? Is it customized?
If customized can you please facilitate me the website of the company who designed it for you?
I would apreciate to have him/her do one for me also!

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source