Permalink
Browse files

version 0.0.2

  • Loading branch information...
1 parent de97b99 commit ceec8c60330c3c9c681c921b1dab0bf40fe41a75 @ncri committed Sep 27, 2012
Showing with 159 additions and 38 deletions.
  1. +106 −4 README.md
  2. +9 −3 lib/ajaxify_rails.rb
  3. +1 −1 lib/ajaxify_rails/version.rb
  4. +43 −30 vendor/assets/javascripts/ajaxify_rails/ajaxify_rails.js.coffee
View
110 README.md
@@ -1,10 +1,15 @@
-# Nested Form Fields
+# Ajaxify Rails
Rails gem for automatically turning internal links into ajax links that load content without a full page reload.
-Uses the html5 history interface for changing the url and making the browser's back and forward buttons working with ajax.
-Falls back to a hash based approach for browsers without the history interface (like Internet Explorer).
-Transparently handles redirects and supports flash messages and page titles. Requires Ruby 1.9 and the asset pipeline.
+- Uses the html5 history interface for changing the url and making the browser's back and forward buttons work with ajax.
+- Falls back to a hash based approach for browsers without the history interface (like Internet Explorer version <10)
+- Hash and non-hash URLs are interchangeable.
+- Transparently handles redirects and supports flash messages and page titles.
+- Requires Ruby 1.9 and the asset pipeline.
+- Tested with Chrome, Firefox, Safari and Internet Explorer 8+
+
+Demo: http://ajaxify-demo.herokuapp.com/
Inspired by the pjax_rails gem (https://github.com/rails/pjax_rails)
@@ -22,8 +27,105 @@ In your application.js file add:
//= require ajaxify_rails
+## How it works
+
+Ajaxify Rails automatically turns all absolute and relative internal site links into ajaxified links.
+Clicking an ajaxified link sends an ajax request to rails. Ajaxify Rails makes sure that the request renders
+without layout and inserts the response into the page's content area.
+
## Usage
+### Content Area
+
+Ajaxify Rails assumes that the content area html element has the id 'main'.
+The content area html in your rails app is the container wrapping the yield statement in your layout.
+If yield doesn't have a wrapper in your app, you need to supply one to get Ajaxify Rails working:
+
+ #main
+ = yield
+
+You can change the content wrapper by setting
+
+ Ajaxify.content_container = 'content_container_id'
+
+### Page Title
+
+If you define a method called 'page_title' in your application controller, Ajaxify Rails will use it to set
+the page's title tag after successful ajaxify requests.
+
+### Navigation and other layout updates
+
+It's a common use case to have a navigation that needs to change its appearence and possibly functioning when the user navigates
+to a different section of the page. Ajaxify Rails provides a success callback that is triggered after successful
+ajaxify requests. Just hook into it and make your layout changes:
+
+ Ajaxify.success ->
+ # update navigation and/or other layout elements
+
+
+### Flash Messages
+
+Ajaxify Rails correctly displays your flash messages after ajaxified requests. To do so it stores flash messages in cookies.
+By default, only flash[:notice] is supported. If you are using for example flash[:warning] as well you have to set:
+
+ Ajaxify.flash_types = ['notice', 'warning']
+
+
+### Root Redirects
+
+Sometimes you need to redirect on the root url. For example you might have a localized application with the locale inside the url.
+When a user navigates to your_domain.com he/she gets redirected to e.g. your_domain.com/en/. This works fine in browsers supporting
+the html 5 history api. However, for browsers without the history api like Internet Explorer before version 10, Ajaxify needs hints
+about your url structure to not get confused, creating endless redirects. So, if you need to support those browsers, you need to
+explicitly supply some regex to Ajaxify. For example, if you need to support the root redirects to your_domain.com/en/ and your_domain.com/de/
+you need to hint Ajaxyfiy like this:
+
+ Ajaxify.base_path_regexp = /^(\/en|\/de)/i
+
+
+### Extra Content
+
+Sometimes you need to do non trivial modifications of the layout whenever the content in the main content area of your site changes.
+Ajaxify Rails allows you to attach arbitrary html to ajaxified requests. This extra html is then stripped from the main content
+that is inserted in the content area. But before that a callback is triggered which can be used to grab the extra content and do something with it.
+To use this feature you need to provide a method ajaxify_extra_content in your ApplicationController:
+
+ def ajaxify_extra_content
+ ... your extra html ...
+ end
+
+For example you could provide url for a widget in the layout like this:
+
+ def ajaxify_extra_content
+ "<div id='may_fancy_widget_html'> some html </div>"
+ end
+
+And then, on the client side hook into Ajaxify via the handle_extra_content callback and select the widget html via #ajaxify_content:
+
+ Ajaxify.handle_extra_content = ->
+ $('#my_fancy_widget').html $('#ajaxify_content #my_fancy_widget').html()
+
+
+### Reference: All Options and Callbacks
+
+Here is a reference of all options and callbacks you can set via Ajaxify.option_or_callback:
+
+ option/callback default description
+
+ active true Toggles ajaxifying of links.
+ content_container 'main' Id of the container to insert the main content into ("yield wrapper").
+ base_path_regexp null Regex hint for applications with root url redirects.
+
+ on_before_load null Callback: Called before the ajaxify request is started.
+ on_success null Callback: Called when an ajaxify requests finished successfully.
+ on_success_once null Callback: Like on_success but only called once.
+ handle_extra_content null Callback: Called before extra content is stripped from the ajax request's response.
+
+ flash_types ['notice'] Flash types your Rails app uses. E.g. ['notice', 'warning', 'error']
+ flash_effect null Callback: Called for each flash type after flash is set.
+ clear_flash_effect null Callback: Called for each flash type whenever flash message is not present
+
+Also check the example app source code for usage: https://github.com/ncri/ajaxify_rails_demo_app
## Contributing
View
@@ -29,8 +29,12 @@ def render *args, &block
layout = args[:layout] || current_layout
layout = (layout == 'application' or layout == true) ? false : layout
args[:layout] = layout
- cookies[:flash_notice] = flash[:notice] # make customizable
- flash[:notice] = nil
+
+ flash.keys.each do |key|
+ cookies["flash_#{key}"] = flash[key]
+ flash[key] = nil
+ end
+
extra_content = (respond_to?(:ajaxify_extra_content) ? ajaxify_extra_content : '')
super args
@@ -39,8 +43,10 @@ def render *args, &block
#
current_url_tag = view_context.content_tag(:span, request.fullpath.sub(/\?ajaxified=true&(.*)/, '?\1').sub(/(&|\?)ajaxified=true/, ''),
id: 'ajaxify_location')
+
response_body[0] += view_context.content_tag(:div, current_url_tag + extra_content,
- id: 'ajaxify_content', style: 'display:none', data: { page_title: try(:page_title) })
+ id: 'ajaxify_content', style: 'display:none',
+ data: { page_title: respond_to?(:page_title) ? page_title : nil })
response.body = self.response_body[0]
return
end
@@ -1,3 +1,3 @@
module AjaxifyRails
- VERSION = "0.0.1"
+ VERSION = "0.0.2"
end
@@ -1,19 +1,30 @@
@Ajaxify =
+ # options
+ #
+ active: true
content_container: 'main'
+ handle_extra_content: null
+ base_path_regexp: null
+
+ # callbacks
+ #
on_before_load: null
on_success: null
on_success_once: null
- hash_changed: null
- ignore_hash_change: null
- load_page_from_hash: null
- handle_extra_content: null
- base_path_regexp: null
+ # flash
+ #
flash_types: ['notice']
flash_effect: null
clear_flash_effect: null
+ # internal use only
+ #
+ hash_changed: null
+ ignore_hash_change: null
+ load_page_from_hash: null
+
initial_history_state:
url: window.location.href
data:
@@ -22,39 +33,41 @@
init: ->
- if this.load_page_from_hash
- this.load_page_from_hash = false
- this.on_hash_change()
+ if this.active
- self = this
+ if this.load_page_from_hash
+ this.load_page_from_hash = false
+ this.on_hash_change()
+
+ self = this
- protocol_and_hostname = "#{window.location.protocol}//#{window.location.hostname}"
+ protocol_and_hostname = "#{window.location.protocol}//#{window.location.hostname}"
- $('body').on 'click', "a[href^='/']:not(.no_ajaxify), a[href^='#{protocol_and_hostname}']:not(.no_ajaxify)", ->
+ $('body').on 'click', "a[href^='/']:not(.no_ajaxify), a[href^='#{protocol_and_hostname}']:not(.no_ajaxify)", ->
- $this = $(this)
- self.load
- url: $this.attr('href')
- type: $this.data('method')
- confirm: $this.data('confirm')
+ $this = $(this)
+ self.load
+ url: $this.attr('href')
+ type: $this.data('method')
+ confirm: $this.data('confirm')
- false
+ false
- exclude_selector = ":not(.no_ajaxify):not([enctype='multipart/form-data'])"
- $('body').on 'submit', "form[action^='/']#{exclude_selector},
- form[action^='#{protocol_and_hostname}']#{exclude_selector}", ->
+ exclude_selector = ":not(.no_ajaxify):not([enctype='multipart/form-data'])"
+ $('body').on 'submit', "form[action^='/']#{exclude_selector},
+ form[action^='#{protocol_and_hostname}']#{exclude_selector}", ->
- $this = $(this)
- form_params = $(this).serialize()
- form_params += '&ajaxified=true'
+ $this = $(this)
+ form_params = $(this).serialize()
+ form_params += '&ajaxified=true'
- self.load
- url: $this.attr('action')
- data: form_params
- type: $this.attr('method')
- confirm: $this.data('confirm')
+ self.load
+ url: $this.attr('action')
+ data: form_params
+ type: $this.attr('method')
+ confirm: $this.data('confirm')
- false
+ false
window.onpopstate = (e) ->
@@ -155,7 +168,7 @@
$("##{this.content_container} #ajaxify_content").remove()
- if title != ''
+ if title
document.title = title.replace /&amp;/, '&' # Todo: need to figure out what else needs to be unescaped
this.show_flash()

0 comments on commit ceec8c6

Please sign in to comment.