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 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: <head> .... <script> var history_current_cache = ""; var root_page = ''/upload_media/show_mixer''; url_hash_check = function() { if (browser_id == 1) { var history = $("ie_hash_history"); var iframe = history.contentDocument || history.contentWindow.document; var current_hash = iframe.location.hash + iframe.location.search; // ie splits it if(current_hash != history_current_cache && !(current_hash == "#" && history_current_cache == "")) { location.hash = current_hash; history_current_cache = current_hash; new Ajax.Request(current_hash.replace(/^#/, '''')); } } else if (browser_id == 2) { var current_hash = location.hash; if(current_hash != history_current_cache) { var ajax_hash = current_hash; if (ajax_hash == "") ajax_hash == "/"; new Ajax.Request(current_hash.replace(/^#/, '''')); history_current_cache = current_hash; } } }; init_back_button = function() { if (navigator.appVersion.match(/\bMSIE\b/)) { browser_id = 1; var history = $("ie_hash_history"); var iframe = history.contentWindow.document; iframe.open(); iframe.close(); iframe.location.hash = location.hash + location.search; // ie breaks up the hash //ie_history_click(root_page); if (location.hash == "") { location.hash = history_current_cache = ''#'' + root_page; } new PeriodicalExecuter(function() { url_hash_check(); }, 5.2); } else if (navigator.appName == "Netscape") { browser_id = 2; if (location.hash == "") { location.hash = root_page; history_current_cache = ''#'' + root_page; } new PeriodicalExecuter(function() { url_hash_check(); }, 0.2); } } </script> </head> <body onload="init_back_button()"> <iframe id="ie_hash_history" style="display: none;"></iframe> .... 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); } } }, -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Slain Wilde
2007-Feb-03 06:24 UTC
Re: Rails & Prototype Ajax Back Button Support in IE and FF
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, you will see 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. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Slain Wilde
2007-Feb-03 06:36 UTC
Re: Rails & Prototype Ajax Back Button Support in IE and FF
Small fix: I let ''debug'' for IE in there. Change the ''5.2'' in the init_back_button function, to ''0.2''. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Stephan Wehner
2007-Feb-03 07:06 UTC
Re: Rails & Prototype Ajax Back Button Support in IE and FF
Slain Wilde 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 http://www.contentwithstyle.co.uk/Articles/38/ which I found later than 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 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Slain Wilde
2007-Feb-03 08:38 UTC
Re: Rails & Prototype Ajax Back Button Support in IE and FF
Stephan Wehner wrote:> Slain Wilde 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 > http://www.contentwithstyle.co.uk/Articles/38/ which I found later than > > 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? > > StephanThey 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. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---