pjax_rails 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ PJAX for Rails 3.1+
2
+ ===================
3
+
4
+ Integrate Chris Wanstrath's PJAX into Rails 3.1+ via the asset pipeline.
5
+
6
+ To activate, add this to your app/assets/javascripts/application.js (or whatever bundle you use):
7
+
8
+ //=require pjax
9
+
10
+ All links that match `$('a:not([data-remote]):not([data-behavior]):not([data-skip-pjax])')` will then use PJAX.
11
+
12
+ The PJAX container has to be marked with data-pjax-container attribute, so for example:
13
+
14
+ <body>
15
+ <div>
16
+ <!-- This will not be touched on PJAX updates -->
17
+ <%= Time.now %>
18
+ </div>
19
+
20
+ <div data-pjax-container>
21
+ <!-- PJAX updates will go here -->
22
+ <%= content_tag :h3, 'My site' %>
23
+ <%= link_to 'About me', about_me_path %>
24
+ <!-- The following link will not be pjax'd -->
25
+ <%= link_to 'Google', 'http://google.com', :data-skip-pjax => true %>
26
+ </div>
27
+ </body>
28
+
29
+
30
+ FIXME: Currently the layout is hardcoded to "application". Need to delegate that to the specific layout of the controller.
31
+
32
+ Examples for redirect_pjax_to
33
+ -----------------------------
34
+
35
+ class ProjectsController < ApplicationController
36
+ before_filter :set_project, except: [ :index, :create ]
37
+
38
+ def index
39
+ @projects = current_user.projects
40
+ end
41
+
42
+ def show
43
+ end
44
+
45
+ def create
46
+ @project = Project.create params[:project]
47
+ redirect_pjax_to :show, @project
48
+ end
49
+
50
+ def update
51
+ @project.update_attributes params[:project]
52
+ redirect_pjax_to :show, @project
53
+ end
54
+
55
+ def destroy
56
+ @project.destroy
57
+
58
+ index # set the objects needed for rendering index
59
+ redirect_pjax_to :index
60
+ end
61
+
62
+ private
63
+ def set_project
64
+ @project = current_user.projects.find params[:id].to_i
65
+ end
66
+ end
@@ -0,0 +1 @@
1
+ $ -> $('a:not([data-remote]):not([data-behavior]):not([data-skip-pjax])').pjax('[data-pjax-container]')
@@ -0,0 +1,3 @@
1
+ //= require ./jquery_pjax
2
+ //= require ./page_triggers
3
+ //= require ./enable_pjax
@@ -0,0 +1,208 @@
1
+ // jquery_pjax.js
2
+ // copyright chris wanstrath
3
+ // https://github.com/defunkt/pjax
4
+
5
+ // When called on a link, fetches the href with ajax into the
6
+ // container specified as the first parameter or with the data-pjax
7
+ // attribute on the link itself.
8
+ //
9
+ // Tries to make sure the back button and ctrl+click work the way
10
+ // you'd expect.
11
+ //
12
+ // Accepts a jQuery ajax options object that may include these
13
+ // pjax specific options:
14
+ //
15
+ // container - Where to stick the response body. Usually a String selector.
16
+ // $(container).html(xhr.responseBody)
17
+ // push - Whether to pushState the URL. Defaults to true (of course).
18
+ // replace - Want to use replaceState instead? That's cool.
19
+ //
20
+ // For convenience the first parameter can be either the container or
21
+ // the options object.
22
+ //
23
+ // Returns the jQuery object
24
+ $.fn.pjax = function( container, options ) {
25
+ if ( options )
26
+ options.container = container
27
+ else
28
+ options = $.isPlainObject(container) ? container : {container:container}
29
+
30
+ return this.live('click', function(event){
31
+ // Middle click, cmd click, and ctrl click should open
32
+ // links in a new tab as normal.
33
+ if ( event.which > 1 || event.metaKey )
34
+ return true
35
+
36
+ var defaults = {
37
+ url: this.href,
38
+ container: $(this).attr('data-pjax')
39
+ }
40
+
41
+ $.pjax($.extend({}, defaults, options))
42
+
43
+ event.preventDefault()
44
+ })
45
+ }
46
+
47
+
48
+ // Loads a URL with ajax, puts the response body inside a container,
49
+ // then pushState()'s the loaded URL.
50
+ //
51
+ // Works just like $.ajax in that it accepts a jQuery ajax
52
+ // settings object (with keys like url, type, data, etc).
53
+ //
54
+ // Accepts these extra keys:
55
+ //
56
+ // container - Where to stick the response body.
57
+ // $(container).html(xhr.responseBody)
58
+ // push - Whether to pushState the URL. Defaults to true (of course).
59
+ // replace - Want to use replaceState instead? That's cool.
60
+ //
61
+ // Use it just like $.ajax:
62
+ //
63
+ // var xhr = $.pjax({ url: this.href, container: '#main' })
64
+ // console.log( xhr.readyState )
65
+ //
66
+ // Returns whatever $.ajax returns.
67
+ $.pjax = function( options ) {
68
+ var $container = $(options.container),
69
+ success = options.success || $.noop
70
+
71
+ // We don't want to let anyone override our success handler.
72
+ delete options.success
73
+
74
+ var defaults = {
75
+ timeout: 1500,
76
+ push: true,
77
+ replace: false,
78
+ // We want the browser to maintain two separate internal caches: one for
79
+ // pjax'd partial page loads and one for normal page loads. Without
80
+ // adding this secret parameter, some browsers will often confuse the two.
81
+ data: { _pjax: true },
82
+ type: 'GET',
83
+ dataType: 'html',
84
+ beforeSend: function(xhr){
85
+ $(document).trigger('start.pjax')
86
+ xhr.setRequestHeader('X-PJAX', 'true')
87
+ },
88
+ error: function(){
89
+ window.location = options.url
90
+ },
91
+ complete: function(){
92
+ $(document).trigger('end.pjax')
93
+ },
94
+ success: function(data){
95
+ // If we got no data or an entire web page, go directly
96
+ // to the page and let normal error handling happen.
97
+ if ( !$.trim(data) || /<html/i.test(data) )
98
+ return window.location = options.url
99
+
100
+ // Make it happen.
101
+ $container.html(data)
102
+
103
+ // If there's a <title> tag in the response, use it as
104
+ // the page's title.
105
+ var oldTitle = document.title,
106
+ title = $.trim( $container.find('title').remove().text() )
107
+ if ( title ) document.title = title
108
+
109
+ var state = {
110
+ pjax: options.container,
111
+ timeout: options.timeout
112
+ }
113
+
114
+ // We can't persist $objects using the history API so we need to store
115
+ // the string selector.
116
+ if ( $.isPlainObject(state.pjax) )
117
+ state.pjax = state.pjax.selector
118
+
119
+ // If there are extra params, save the complete URL in the state object
120
+ var query = $.param(options.data)
121
+ if ( query != "_pjax=true" )
122
+ state.url = options.url + (/\?/.test(options.url) ? "&" : "?") + query
123
+
124
+ if ( options.replace ) {
125
+ window.history.replaceState(state, document.title, options.url)
126
+ } else if ( options.push ) {
127
+ // this extra replaceState before first push ensures good back
128
+ // button behavior
129
+ if ( !$.pjax.active ) {
130
+ window.history.replaceState($.extend({}, state, {url:null}), oldTitle)
131
+ $.pjax.active = true
132
+ }
133
+
134
+ window.history.pushState(state, document.title, options.url)
135
+ }
136
+
137
+ // Google Analytics support
138
+ if ( (options.replace || options.push) && window._gaq )
139
+ _gaq.push(['_trackPageview'])
140
+
141
+ // Invoke their success handler if they gave us one.
142
+ success.apply(this, arguments)
143
+ }
144
+ }
145
+
146
+ options = $.extend(true, {}, defaults, options)
147
+
148
+ if ( $.isFunction(options.url) ) {
149
+ options.url = options.url()
150
+ }
151
+
152
+ // Cancel the current request if we're already pjaxing
153
+ var xhr = $.pjax.xhr
154
+ if ( xhr && xhr.readyState < 4) {
155
+ xhr.onreadystatechange = $.noop
156
+ xhr.abort()
157
+ }
158
+
159
+ $.pjax.xhr = $.ajax(options)
160
+ $(document).trigger('pjax', $.pjax.xhr, options)
161
+
162
+ return $.pjax.xhr
163
+ }
164
+
165
+
166
+ // Used to detect initial (useless) popstate.
167
+ // If history.state exists, assume browser isn't going to fire initial popstate.
168
+ var popped = ('state' in window.history), initialURL = location.href
169
+
170
+
171
+ // popstate handler takes care of the back and forward buttons
172
+ //
173
+ // You probably shouldn't use pjax on pages with other pushState
174
+ // stuff yet.
175
+ $(window).bind('popstate', function(event) {
176
+ // Ignore inital popstate that some browsers fire on page load
177
+ var initialPop = !popped && location.href == initialURL
178
+ popped = true
179
+ if ( initialPop ) return
180
+
181
+ var state = event.state
182
+
183
+ if ( state && state.pjax ) {
184
+ var $container = $(state.pjax+'')
185
+ if ( $container.length )
186
+ $.pjax({
187
+ url: state.url || location.href,
188
+ container: $container,
189
+ push: false,
190
+ timeout: state.timeout
191
+ })
192
+ else
193
+ window.location = location.href
194
+ }
195
+ })
196
+
197
+
198
+ // Add the state property to jQuery's event object so we can use it in
199
+ // $(window).bind('popstate')
200
+ if ( $.event.props.indexOf('state') < 0 )
201
+ $.event.props.push('state')
202
+
203
+
204
+ // Fall back to normalcy for older browsers.
205
+ if ( !window.history || !window.history.pushState ) {
206
+ $.pjax = $.noop
207
+ $.fn.pjax = function() { return this }
208
+ }
@@ -0,0 +1,10 @@
1
+ $(document).ready ->
2
+ $(document).trigger 'pageChanged'
3
+ $(document).trigger 'pageUpdated'
4
+
5
+ $(document).bind 'end.pjax', ->
6
+ $(document).trigger 'pageChanged'
7
+ $(document).trigger 'pageUpdated'
8
+
9
+ $(document).bind 'ajaxComplete', ->
10
+ $(document).trigger 'pageUpdated'
data/lib/pjax.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Pjax
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ layout ->(c) { pjax_request? ? false : 'application' }
6
+ end
7
+
8
+ private
9
+ def redirect_pjax_to(action, url = nil)
10
+ new_url = url_for(url ? url : { action: action })
11
+
12
+ render js: <<-EJS
13
+ if (!window.history || !window.history.pushState) {
14
+ window.location.href = '#{new_url}';
15
+ } else {
16
+ $('[data-pjax-container]').html(#{render_to_string("#{action}.html.erb").to_json});
17
+ $(document).trigger('end.pjax');
18
+
19
+ var title = $.trim($('[data-pjax-container]').find('title').remove().text());
20
+ if (title) document.title = title;
21
+ window.history.pushState({}, document.title, '#{new_url}');
22
+ }
23
+ EJS
24
+ end
25
+
26
+ def pjax_request?
27
+ env['HTTP_X_PJAX'].present?
28
+ end
29
+ end
data/lib/pjax_rails.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'pjax'
2
+
3
+ module PjaxRails
4
+ class Engine < ::Rails::Engine
5
+ initializer "pjax_rails.add_controller" do
6
+ config.to_prepare { ApplicationController.send :include, Pjax }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'pjax_rails'
3
+ s.version = '0.1.5'
4
+ s.author = 'David Heinemeier Hansson (PJAX by Chris Wanstrath)'
5
+ s.email = 'david@loudthinking.com'
6
+ s.summary = 'PJAX integration for Rails 3.1+'
7
+
8
+ s.add_dependency 'jquery-rails'
9
+
10
+ s.files = Dir["#{File.dirname(__FILE__)}/**/*"]
11
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pjax_rails
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.5
6
+ platform: ruby
7
+ authors:
8
+ - David Heinemeier Hansson (PJAX by Chris Wanstrath)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-26 00:00:00 -05:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: jquery-rails
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description:
28
+ email: david@loudthinking.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files: []
34
+
35
+ files:
36
+ - ./lib/assets/javascripts/pjax/enable_pjax.js.coffee
37
+ - ./lib/assets/javascripts/pjax/index.js
38
+ - ./lib/assets/javascripts/pjax/jquery_pjax.js
39
+ - ./lib/assets/javascripts/pjax/page_triggers.js.coffee
40
+ - ./lib/pjax.rb
41
+ - ./lib/pjax_rails.rb
42
+ - ./pjax_rails.gemspec
43
+ - ./README.md
44
+ has_rdoc: true
45
+ homepage:
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.6.2
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: PJAX integration for Rails 3.1+
72
+ test_files: []
73
+