# Rails & Prototype Ajax Back Button Support in IE and FF

**URL:** <https://www.ruby-forum.com/t/rails-prototype-ajax-back-button-support-in-ie-and-ff/84331>\
**Category:** Rails\
**Created:** [February 3, 2007, 7:16am UTC](https://www.ruby-forum.com/t/rails-prototype-ajax-back-button-support-in-ie-and-ff/84331 "2007-02-03T07:16:26Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![slain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2acd7d/32.png) [@slain](https://www.ruby-forum.com/u/slain)\
**Post date:** [February 3, 2007, 7:16am UTC](https://www.ruby-forum.com/t/rails-prototype-ajax-back-button-support-in-ie-and-ff/84331/1 "2007-02-03T07:16:26Z")

</div>

So I adapted some of the other methods of using the anchor href hash.  
Much of this concept I got from  
[http://www.mikage.to/jquery/jquery\_history.html](http://www.mikage.to/jquery/jquery_history.html) and adapted to Prototype  
javascript.

This method works as follows:  
You use a custom helper method, called history\_remote, instead of  
link\_to\_remote whenever you want a new ‘page’ that can be navigated to  
using the back/forward buttons in the browser, or bookmarked. This adds  
another parameter to the Ajax.Request in the onclick of the ahref,  
history:true, which tells Ajax.Request to do the back button handling if  
it is IE or FF. Other browsers should be unaffected, but without  
support for back button.

Add this to your application\_helper.rb:  
module ActionView  
module Helpers  
module PrototypeHelper

def history\_remote(name, options = {}, html\_options = {})  
options[:history] = true  
function = remote\_function(options);  
function.gsub!(/asynchronous:true/, ‘asynchronous:true,  
history:true’)  
link\_to\_function(name, function, html\_options)  
end  
end  
end  
end

Add this to your application layout.rhtml:

........

Add the following function to the prototype.js:  
/////////////////////////////////////////////////////////////  
// this needs to be here even if history is disabled  
var browser\_id = 0;  
ie\_history\_click = function(hash) {  
var newhash = ‘#’ + hash;  
location.hash = newhash;  
var history = $(“ie\_hash\_history”);  
var iframe = history.contentWindow.document;  
iframe.open();  
iframe.close();  
iframe.location.hash = newhash;  
}  
////////////////////////////////////////////////////////////

And modify the Ajax.Request request function to this:  
request: function(url) {

```
if (browser_id == 1 && this.options.history == true) {
  ie_history_click(url);
} else if (browser_id == 2 && this.options.history == true) {
  parent.location = '#' + url;
} else {
  // we want to actually call for all other browsers and for

```

non-history  
// links in IE and FF  
var parameters = this.options.parameters || ‘’;  
if (parameters.length \> 0) parameters += ‘&\_=’;

```
  try {
    this.url = url;
    if (this.options.method == 'get' && parameters.length > 0)
      this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;

    Ajax.Responders.dispatch('onCreate', this, this.transport);

    this.transport.open(this.options.method, this.url,
      this.options.asynchronous);

    if (this.options.asynchronous) {
      this.transport.onreadystatechange =

```

this.onStateChange.bind(this);  
setTimeout((function()  
{this.respondToReadyState(1)}).bind(this), 10);  
}

```
    this.setRequestHeaders();

    var body = this.options.postBody ? this.options.postBody :

```

parameters;  
this.transport.send(this.options.method == ‘post’ ? body :  
null);

```
  } catch (e) {
    this.dispatchException(e);
  }
}

```

},

---

<div class="post-metadata">

**Author:** ![slain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2acd7d/32.png) [@slain](https://www.ruby-forum.com/u/slain)\
**Post date:** [February 3, 2007, 7:24am UTC](https://www.ruby-forum.com/t/rails-prototype-ajax-back-button-support-in-ie-and-ff/84331/2 "2007-02-03T07:24:06Z")

</div>

Some more info:

Basically this sets up a periodical updater, that checks the location  
‘hash’, the stuff after the # sign in a URL. To support the back  
button, I convert the :url to a hash instead.

So if your action is at [http://localhost/my\_controller/my\_action/my\_id](http://localhost/my_controller/my_action/my_id),  
you will see [http://localhost/#/my\_controller/my\_action/my\_id](http://localhost/#/my_controller/my_action/my_id) in your  
location bar. When you click a link in IE or FF, the only thing that  
really happens is that the location bar url changes, then the periodical  
update notices a split second later and makes the actual Ajax.Request to  
do the change. (In IE it actually does some more magic with an IFRAME.)  
It also works with Ajax.Updater since it uses the Ajax.Request’s request  
method.

---

<div class="post-metadata">

**Author:** ![slain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2acd7d/32.png) [@slain](https://www.ruby-forum.com/u/slain)\
**Post date:** [February 3, 2007, 7:36am UTC](https://www.ruby-forum.com/t/rails-prototype-ajax-back-button-support-in-ie-and-ff/84331/3 "2007-02-03T07:36:57Z")

</div>

Small fix: I let ‘debug’ for IE in there. Change the ‘5.2’ in the  
init\_back\_button function, to ‘0.2’.

---

<div class="post-metadata">

**Author:** ![slain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2acd7d/32.png) [@slain](https://www.ruby-forum.com/u/slain)\
**Post date:** [February 3, 2007, 9:38am UTC](https://www.ruby-forum.com/t/rails-prototype-ajax-back-button-support-in-ie-and-ff/84331/4 "2007-02-03T09:38:27Z")

</div>

Stephan W. wrote:

> Slain W. wrote:
> 
> > Small fix: I let ‘debug’ for IE in there. Change the ‘5.2’ in the  
> > init\_back\_button function, to ‘0.2’.
> 
> Your work sounds very useful. I remember when I was looking at the  
> backbutton a year ago, there were several javascript solutions  
> available; I think I liked this one  
> [Content with Style](http://www.contentwithstyle.co.uk/Articles/38/) which I found later than
> 
> [History Keeper – Deep Linking in Flash & JavaScript – unFocus Projects – Kevin Newman and Ken Newman](http://www.unfocus.com/Projects/HistoryKeeper/)
> 
> which I am actually using.
> 
> I also remember one approach needed different treatments for FF, IE, and  
> Safari.
> 
> How does the solution you chose compare?
> 
> Stephan

They all use pretty much the same technique that this does. This just  
makes it really easy to use in Rails/Prototype without having to add  
JQuery, or Dojo, or some other framework. Using ‘history\_remote’ instead  
of ‘link\_to\_remote’ is dead simple as far as what it takes to convert  
your site. It took me all of 5 minutes.

One of the key things about this solution, with my redefinition of  
Ajax.Request#request, is that it doesn’t affect page or fragment caching  
at all, since the links look identical across all browsers.

Many of the other techniques require you to add a class=“remote” or  
similar to all of the links, requiring you to run thru all of the links  
on the page and changing the onclick behavior. Because of this, some of  
them don’t support ‘backable’ links inside the content updated in an  
Ajax.Request (at least without adding some additional javascript either  
at the end of your update which can get tricky since the request  
completes before the links are rendered).

Also, using the actual url\_for stuff as the location bar hash definition  
seems to be novel in the ones I’ve reviewed. It makes it easy to know  
where you are when debugging, and allows external bookmarks to work  
without lots of hoops.

Safari support I will look into. It (and Opera) will work fine on the  
same site withOUT back button support, but a different technique is  
required for Safari that for my clients isn’t a huge issue since it  
still works.

The only mild annoyance right now, is if you bookmark one of these hash  
links, when you use that bookmark, it will load the / root page then  
load the page you wanted. Depending on how you design your site, you  
can tweak the init\_back\_button function to handle it. If anyone needs  
help with that, post here.

---

<div class="post-metadata">

**Author:** ![slain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2acd7d/32.png) [@slain](https://www.ruby-forum.com/u/slain)\
**Post date:** [February 3, 2007, 8:06am UTC](https://www.ruby-forum.com/t/rails-prototype-ajax-back-button-support-in-ie-and-ff/84331/5 "2007-02-03T08:06:03Z")

</div>

Slain W. wrote:

> Small fix: I let ‘debug’ for IE in there. Change the ‘5.2’ in the  
> init\_back\_button function, to ‘0.2’.

Your work sounds very useful. I remember when I was looking at the  
backbutton a year ago, there were several javascript solutions  
available; I think I liked this one  
[Content with Style](http://www.contentwithstyle.co.uk/Articles/38/) which I found later than

[http://www.unfocus.com/Projects/HistoryKeeper/](http://www.unfocus.com/Projects/HistoryKeeper/)

which I am actually using.

I also remember one approach needed different treatments for FF, IE, and  
Safari.

How does the solution you chose compare?

Stephan
