Veerasundaravel's Ruby on Rails Weblog

December 2, 2011

Change browser URL without reloading the page – jQuery – HTML5

Filed under: jQuery, Ruby On Rails — Tags: , , , , — Veerasundaravel @ 4:14 pm

The traditional way of changing the browser url is just adding hash to the end of current URL like window.location = “#q=test&sort=date”;

But if you want to change complete url like window.location = “/profile/show/1”; will redirect the user to that page but it will reload page. So how we can change browser URL with reloading  the page. The better solution is HTML5 History API. More ever the jQuery plugin History.js provides lot easier configuration and options to achieve this.

History.js:

History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.

Download & Installation:

  1. Download History.js and upload it to your webserver. Download links: tar.gz or zip
  2. Include History.js
    • For jQueryv1.3+
      <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
    • For Mootoolsv1.3+
      <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/mootools.history.js"></script>
    • For Right.jsv2.2+
      <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/right.history.js"></script>
    • For Zeptov0.5+
      <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/zepto.history.js"></script>
    • For everything else
      <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/native.history.js"></script>

Note: If you want to only support HTML5 Browsers and not HTML4 Browsers (so no hash fallback support) then just change the /html4+html5/ part in the urls to just /html5/. Why supporting HTML4 browsers could be either good or bad based on my app’s use cases

Working with History.js:

once after including the javascript you can change the browser URL just by calling any one the js statement.

History.pushState({state:1}, “State 1”, “?state=1”); (or) History.replaceState({state:3}, “State 3”, “?state=3”)

(function(window,undefined){

    // Prepare
    var History = window.History; // Note: We are using a capital H instead of a lower h
    if ( !History.enabled ) {
         // History.js is disabled for this browser.
         // This is because we can optionally choose to support HTML4 browsers or not.
        return false;
    }

    // Bind to StateChange Event
    History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
        var State = History.getState(); // Note: We are using History.getState() instead of event.state
        History.log(State.data, State.title, State.url);
    });

    // Change our States
    History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1"
    History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2"
    History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3"
    History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4"
    History.back(); // logs {state:3}, "State 3", "?state=3"
    History.back(); // logs {state:1}, "State 1", "?state=1"
    History.back(); // logs {}, "Home Page", "?"
    History.go(2); // logs {state:3}, "State 3", "?state=3"

})(window);

How would the above operations look in a HTML5 Browser?

  1. www.mysite.com
  2. www.mysite.com/?state=1
  3. www.mysite.com/?state=2
  4. www.mysite.com/?state=3
  5. www.mysite.com/?state=4
  6. www.mysite.com/?state=3
  7. www.mysite.com/?state=1
  8. www.mysite.com
  9. www.mysite.com/?state=3

Note: These urls also work in HTML4 browsers and Search Engines. So no need for the hashbang (#!) fragment-identifier that google “recommends”.

How would they look in a HTML4 Browser?

  1. www.mysite.com
  2. www.mysite.com/#?state=1&_suid=1
  3. www.mysite.com/#?state=2&_suid=2
  4. www.mysite.com/#?state=3&_suid=3
  5. www.mysite.com/#?state=4
  6. www.mysite.com/#?state=3&_suid=3
  7. www.mysite.com/#?state=1&_suid=1
  8. www.mysite.com
  9. www.mysite.com/#?state=3&_suid=3

For further detailed documentation and queries you can refer : https://github.com/balupton/history.js/blob/master/README.md

November 18, 2011

link_to_remote With Rails 3 and UJS

Filed under: Rails3 — Tags: , , , , , , , — Veerasundaravel @ 3:46 pm

Rails 3 has adopted Unobtrusive Javascript and moved all the _remote functions to a plugin called prototype_legacy_helper. You can view the release note about this here. They did this in an effort to remove all the inline nasty code produced by the helpers and provide a more modular way to deal with Javascript & Ajax.

What this means is that all previous remote_<method> helpers have been removed from Rails core. To get UJS hooks into your HTML, you can now pass :remote => true instead. For example:

in Rails2:

link_to_remote('Refresh', :update => "emails", :url => {:controller=>"mail", :action => "list_emails" })

#will result

<a href="#" onclick="new Ajax.Updater('emails', '/mail/list_emails', {asynchronous:true, evalScripts:true}); 
return false;">Refresh</a>

 

in Rails3:

link_to 'Refresh', {:controller=>"mail", :action => 'list_emails'}, :remote=> true 

#will result

<a href="/mail/list_emails" data-remote="true">Refresh</a>

This makes it very easy for a javascript driver to come along, pick out and identify the relevant pieces, and attach the appropriate handlers.

Grab the jQuery UJS driver at http://github.com/rails/jquery-ujs and put it in your javascripts directory. The file is at src/rails.js

Include jQuery and the UJS driver in your application layout or view. Then the Rails UJS driver look for links and forms with a data-remote=”true” attribute and AJAX-ify them. So now our <a> tag can fire a Ajax request.

 

Ajax Callbacks:

With good old link_to_remote we could pass an :update option to achieve the system described above, in which the page receives a generic response and updates the specified element with it. But link_to doesn’t accept an :update option because with Rails 3 and UJS we want to avoid putting JavaScript in our <a> tag attributes.

So how do we do this? If we don’t write the code that makes the AJAX request, how can we access the response? The answer is: events.

 

The UJS drivers trigger six events on every AJAX call:

  • ajax:before
  • ajax:loading
  • ajax:success
  • ajax:failure
  • ajax:complete
  • ajax:after

You should recognize these event names from the old link_to_remote method options, and we simply need to listen for them on our AJAX-triggering elements.

 

Example:

Let’s say we have a page that lists the ten most popular products in our database. At the end is a link to load all the remaining products via AJAX:

<ul id="products-list">
  <li>...</li>
  <li>...</li>
  <li>...</li>
 ...
</ul>
<%= link_to "more...", "/products/all", :id => "load-more", :remote => true %>

The server returns plain HTML and we use the ajax:x events triggered by the Rails UJS drivers (here jQuery) to grab the server’s response and insert it into the right element on the page:

<%= javascript_tag do %>
  $("#load-more").bind("ajax:complete", function(et, e){
    $("#products-list").html(e.responseText); // insert content
  });
<% end %>

If desired, we can also use the ajax:loading event to change the link text (or show a spinner):

<%= javascript_tag do %>
  $("#load-more").bind("ajax:loading", function(et, e){
    $(this).html("Loading..."); // swap link text
  });
<% end %>

 

Use the forgery protection meta tags: <%= csrf_meta_tag %>:

This tag will return meta tags with the cross-site request forgery protection token for forms to use. Place this in your head, it will return meta tags as follows:

<metaname="csrf-param"content="authenticity_token"/>
<metaname="csrf-token"content="pACcWm38PxTmGUoz2bSmKIzIwpEmqCJDTH6xe2="/>

Don’t hardcode these tags or values. Also in Rails 3.1, csrf_meta_tag has been renamed to csrf_meta_tags.

September 16, 2010

Styling the Browse button using jQuery

Browsers do not let you style file inputs. File Style plugin fixes this problem. It enables you to use image as browse button. You can also style filename field as normal textfield using css. It is written using JavaScript and jQuery.

Want to see how it works? Check the demo page.

Thanks to RajaSelvam for introducing this plugin.

Reference URL: http://www.appelsiini.net/projects/filestyle

Older Posts »

%d bloggers like this: