ajax_pagination 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +20 -1
- data/README.md +49 -5
- data/Rakefile +16 -0
- data/ajax_pagination.gemspec +5 -2
- data/lib/ajax_pagination/controller_additions.rb +52 -3
- data/lib/ajax_pagination/helper_additions.rb +53 -4
- data/lib/ajax_pagination/version.rb +1 -1
- data/lib/assets/images/ajax-loader.gif +0 -0
- data/lib/assets/javascripts/ajax_pagination.js.erb +41 -31
- data/spec/PORT +1 -0
- data/spec/ajax_pagination/controller_additions_spec.rb +79 -0
- data/spec/ajax_pagination/helper_additions_spec.rb +45 -0
- data/spec/ajax_pagination/integration/ajaxpaginate_spec.rb +33 -0
- data/spec/ajax_pagination/integration/nojavascript_spec.rb +30 -0
- data/spec/ajax_pagination/integration/paginate_spec.rb +30 -0
- data/spec/rails_app/.gitignore +8 -0
- data/spec/rails_app/Gemfile +42 -0
- data/spec/rails_app/README.rdoc +261 -0
- data/spec/rails_app/Rakefile +7 -0
- data/spec/rails_app/app/assets/javascripts/application.js +17 -0
- data/spec/rails_app/app/assets/javascripts/posts.js +2 -0
- data/spec/rails_app/app/assets/stylesheets/application.css +26 -0
- data/spec/rails_app/app/assets/stylesheets/posts.css +4 -0
- data/spec/rails_app/app/assets/stylesheets/scaffold.css +56 -0
- data/spec/rails_app/app/controllers/application_controller.rb +10 -0
- data/spec/rails_app/app/controllers/changelog_controller.rb +13 -0
- data/spec/rails_app/app/controllers/pages_controller.rb +23 -0
- data/spec/rails_app/app/controllers/posts_controller.rb +95 -0
- data/spec/rails_app/app/controllers/sessions_controller.rb +11 -0
- data/spec/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_app/app/helpers/posts_helper.rb +2 -0
- data/spec/rails_app/app/mailers/.gitkeep +0 -0
- data/spec/rails_app/app/models/.gitkeep +0 -0
- data/spec/rails_app/app/models/changelog.rb +19 -0
- data/spec/rails_app/app/models/post.rb +4 -0
- data/spec/rails_app/app/views/changelog/_page.html.erb +10 -0
- data/spec/rails_app/app/views/changelog/index.html.erb +3 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +37 -0
- data/spec/rails_app/app/views/pages/about.html.erb +4 -0
- data/spec/rails_app/app/views/pages/readme.html.erb +4 -0
- data/spec/rails_app/app/views/pages/welcome.html.erb +6 -0
- data/spec/rails_app/app/views/posts/_form.html.erb +29 -0
- data/spec/rails_app/app/views/posts/_page.html.erb +15 -0
- data/spec/rails_app/app/views/posts/_upcomingpage.html.erb +15 -0
- data/spec/rails_app/app/views/posts/edit.html.erb +6 -0
- data/spec/rails_app/app/views/posts/index.html.erb +15 -0
- data/spec/rails_app/app/views/posts/new.html.erb +5 -0
- data/spec/rails_app/app/views/posts/show.html.erb +13 -0
- data/spec/rails_app/config.ru +4 -0
- data/spec/rails_app/config/application.rb +56 -0
- data/spec/rails_app/config/boot.rb +10 -0
- data/spec/rails_app/config/database.yml +25 -0
- data/spec/rails_app/config/environment.rb +5 -0
- data/spec/rails_app/config/environments/development.rb +37 -0
- data/spec/rails_app/config/environments/production.rb +67 -0
- data/spec/rails_app/config/environments/test.rb +37 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/inflections.rb +15 -0
- data/spec/rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_app/config/initializers/secret_token.rb +7 -0
- data/spec/rails_app/config/initializers/session_store.rb +8 -0
- data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails_app/config/locales/en.yml +5 -0
- data/spec/rails_app/config/routes.rb +72 -0
- data/spec/rails_app/db/development.sqlite3 +0 -0
- data/spec/rails_app/db/migrate/20120219063632_create_posts.rb +10 -0
- data/spec/rails_app/db/migrate/20120219130149_add_published_to_post.rb +5 -0
- data/spec/rails_app/lib/assets/.gitkeep +0 -0
- data/spec/rails_app/log/.gitkeep +0 -0
- data/spec/rails_app/public/404.html +26 -0
- data/spec/rails_app/public/422.html +26 -0
- data/spec/rails_app/public/500.html +25 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/script/rails +6 -0
- data/spec/rails_app/test/fixtures/posts.yml +9 -0
- data/spec/rails_app/test/functional/posts_controller_test.rb +49 -0
- data/spec/rails_app/test/unit/helpers/posts_helper_test.rb +4 -0
- data/spec/rails_app/test/unit/post_test.rb +7 -0
- data/spec/spec_helper.rb +28 -0
- data/vendor/assets/javascripts/jquery.url.js +160 -0
- metadata +171 -86
data/.travis.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.8.7
|
4
|
+
- 1.9.2
|
5
|
+
- 1.9.3
|
6
|
+
- rbx-18mode
|
7
|
+
- rbx-19mode
|
8
|
+
# Can't get to work (if anybody wants to fix this, please do)
|
9
|
+
# - jruby-18mode # JRuby in 1.8 mode
|
10
|
+
# - jruby-19mode # JRuby in 1.9 mode
|
11
|
+
|
12
|
+
# uncomment this line if your project needs to run something other than `rake`:
|
13
|
+
before_script: # for Selenium RSpec tests
|
14
|
+
- "export DISPLAY=:99.0"
|
15
|
+
- "sh -e /etc/init.d/xvfb start"
|
16
|
+
script: rake travis
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
## v0.1.0
|
2
|
+
* Added functional tests for controller and helper additions.
|
3
|
+
* Mocked up a rails application using ajax_pagination, at spec/rails_app/. You can run this example application using:
|
4
|
+
|
5
|
+
```sh
|
6
|
+
bundle install
|
7
|
+
bundle exec rails server
|
8
|
+
```
|
9
|
+
|
10
|
+
* Added more mock changelog model and controller (including various dummy informational pages) to test application.
|
11
|
+
* Modified controller and helper additions, so that they are more suitable for ajaxifying menu navigations.
|
12
|
+
* Added loadzone option to the ajax_pagination helper, so that ajax_pagination_loadzone does not need to be used.
|
13
|
+
* Modularised javascript further so only a single function is globally accessible through the jQuery object.
|
14
|
+
* Example application shows nested AJAX pagination, and multiple AJAX paginated sections in one page.
|
15
|
+
* Default loading image added to gem.
|
16
|
+
* urlregex parameter on the reload option extended with urlpart, to make it easier to specify a regular expression on only part of the url. Gem now depends on jquery.url.js as well (vendorized automatically, same as with the jquery.ba-bbq.js dependency).
|
17
|
+
* Added some RSpec tests on example application with and without javascript
|
18
|
+
* Make rake travis task for easy testing (automatically starts up daemonized webrick server for selenium tests, also cleans up the daemon). The test script will clone the development database to create a test database. There is a bundling problem with the external javascript dependencies (those inside other gems), so the script also copies the javascript files into a local vendor/assets/javascripts directory (keeping them up-to-date).
|
19
|
+
|
1
20
|
## v0.0.2
|
2
21
|
* Semi-transparent white rectangle changed to completely transparent rectangle. Instead, the opacity of the content behind it is lowered to achieve the same effect, but works better on backgrounds of other colours as well.
|
3
22
|
* Added rdoc comments to code
|
@@ -5,5 +24,5 @@
|
|
5
24
|
|
6
25
|
## v0.0.1
|
7
26
|
|
8
|
-
* initial release
|
27
|
+
* initial release.
|
9
28
|
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# AJAX Pagination
|
2
|
+
[![Build Status](https://secure.travis-ci.org/ronalchn/ajax_pagination.png?branch=master)](http://travis-ci.org/ronalchn/ajax_pagination)
|
2
3
|
|
3
4
|
Handles AJAX pagination for you, by hooking up the links you want to load content with javascript in designated page containers. Each webpage can have multiple page containers, each with a different set of pagination links. The page containers can be nested. Degrades gracefully when javascript is disabled.
|
4
5
|
|
@@ -68,13 +69,13 @@ This will cause it to display content in the _mypartial.* view.
|
|
68
69
|
|
69
70
|
If you are using will_paginate, and the links are wrapped in a div with class="pagination", the links will be ajaxified automatically.
|
70
71
|
|
71
|
-
Otherwise, you should wrap the links with a container. We recommend that the class given is "ajaxpagination".
|
72
|
+
Otherwise, you should wrap the links with a container. We recommend that the class given is "ajaxpagination". You can put the links inside the partial, for example:
|
72
73
|
|
73
74
|
```html
|
74
75
|
<div class="ajaxpagination"><a href="#">My ajaxified link</a></div>
|
75
76
|
```
|
76
77
|
|
77
|
-
If you are using will_paginate, you can simply put
|
78
|
+
If you are using will_paginate, you can simply put the links inside the partial (so that the new links get reloaded when the page changes):
|
78
79
|
|
79
80
|
```erb
|
80
81
|
<%= will_paginate @objects, :params => { :pagination => nil } %>
|
@@ -84,6 +85,25 @@ Note: It is recommended to set the pagination parameter to nil. When AJAX pagina
|
|
84
85
|
|
85
86
|
Now, AJAX Pagination will automatically call the controller for new content when an ajaxified link is clicked.
|
86
87
|
|
88
|
+
If the links are outside the partial, you will need to also let AJAX Pagination know what content container should be reloaded when the links are followed. In this case, the div with ajaxpagination class should define the data-pagination attribute, the value corresponding to the name of the pagination content, for example you can do the following (which ajaxifies the menu navigation links):
|
89
|
+
|
90
|
+
```erb
|
91
|
+
<div class="ajaxpagination menu" data-pagination="menu">
|
92
|
+
<ul>
|
93
|
+
<li><%= link_to "Home", root_url %></li>
|
94
|
+
<li><%= link_to "Posts", posts_url %></li>
|
95
|
+
<li><%= link_to "Changelog", changelog_url %></li>
|
96
|
+
<li><%= link_to "Readme", pages_readme_url %></li>
|
97
|
+
<li><%= link_to "About", pages_about_url %></li>
|
98
|
+
</ul>
|
99
|
+
</div>
|
100
|
+
<%= ajax_pagination :pagination => "menu", :reload => {:urlpart => "path", :urlregex => "^.*$"} do %>
|
101
|
+
<%= yield %>
|
102
|
+
<% end %>
|
103
|
+
```
|
104
|
+
|
105
|
+
Incidentally, this example also presents an alternative to passing in a :partial option to <tt>ajax_pagination</tt>. Instead, you can pass it a block, in which case you can call the render helper yourself, or any other function (in this case, yield). If a block is passed, any :partial option is ignored.
|
106
|
+
|
87
107
|
### Controller responder
|
88
108
|
|
89
109
|
However, the controller needs to be told how to respond. Add a call to <tt>ajax_pagination(format)</tt> in the controller action, which will return javascript containing the partial.
|
@@ -105,7 +125,7 @@ The pagination should now work.
|
|
105
125
|
|
106
126
|
### Loading visualization
|
107
127
|
|
108
|
-
AJAX Pagination can also add a loading image and partially blanking out of the paginated content. To do this, wrap all the content you want to cover with <tt>ajax_pagination_loadzone</tt>. For example, in the partial, you might have:
|
128
|
+
AJAX Pagination can also add a loading image and partially blanking out of the paginated content. To do this, you can wrap all the content you want to cover with <tt>ajax_pagination_loadzone</tt>. For example, in the partial, you might have:
|
109
129
|
|
110
130
|
```erb
|
111
131
|
<%= will_paginate @objects, :params => { :pagination => nil } %>
|
@@ -120,6 +140,16 @@ Links outside are still clickable (such as the will_paginate links).
|
|
120
140
|
|
121
141
|
The loading image is currently an image asset at "ajax-loader.gif", so put your loading image there. (TODO: add default loader image, and make the location changeable)
|
122
142
|
|
143
|
+
If you want all the content in the partial (or otherwise wrapped by the ajax_pagination helper method) to be included as a loading zone (with the visual loading cues), you can instead, set the :loadzone option to true, eg:
|
144
|
+
|
145
|
+
```erb
|
146
|
+
<%= ajax_pagination :pagination => "menu", :reload => {:urlpart => "path", :urlregex => "^.*$"}, :loadzone => true do %>
|
147
|
+
<%= yield %>
|
148
|
+
<% end %>
|
149
|
+
```
|
150
|
+
|
151
|
+
In this case, whatever is inside the yield will not need to call ajax_pagination_loadzone.
|
152
|
+
|
123
153
|
### Content reloading
|
124
154
|
|
125
155
|
The back and forward buttons on your browser may not work properly yet. It will work as long as the link includes distinct query parameter with the same name as the pagination name for the set. For example, if the name of the pagination set is "page" (the default), when the browser url changes, AJAX Pagination looks for a change in the links query parameter with the same name, such as if the url changes from /path/to/controller?page=4 to /path/to/controller?page=9, then AJAX Pagination knows that the content corresponding to the pagination set needs reloading. The absence of the parameter is a distinct state, so changes such as /path/to/controller to /path/to/controller?page=0 are detected.
|
@@ -151,6 +181,20 @@ Instead of passing in the Array/Hash Ruby object, a string in json form is accep
|
|
151
181
|
```erb
|
152
182
|
<%= ajax_pagination :reload => '[{"urlregex":"page=([0-9]+)","regexindex":1},{"query":"page"}]' %>
|
153
183
|
```
|
184
|
+
## Example Application
|
185
|
+
This gem contains an example application (actually, it is there also for testing purposes), however it is nevertheless a good example.
|
186
|
+
|
187
|
+
Clone this repository, and run the server, using:
|
188
|
+
|
189
|
+
```sh
|
190
|
+
git clone git://github.com/ronalchn/ajax_pagination.git
|
191
|
+
cd ajax_pagination
|
192
|
+
cd spec/rails_app
|
193
|
+
bundle install
|
194
|
+
bundle exec rails server
|
195
|
+
```
|
196
|
+
|
197
|
+
Then point your browser to http://localhost:3000/
|
154
198
|
|
155
199
|
## AJAX Call
|
156
200
|
The AJAX Call is triggered by a link wrapped in any container with a certain class. The AJAX Call is to the same address, but with the ?pagination=NAME parameter added. The format requested is javascript. If the controller also returns javascript for other uses, AJAX Pagination does not necessarily prevent such uses. The ajax_pagination(format, :pagination => "page") function in the controller handles the AJAX Call when the format is javascript, and the ?pagination parameter is set to the correct string. It also returns true if the pagination parameter matches. Therefore, you can use use the javascript format when it does not match, as shown below:
|
@@ -173,9 +217,9 @@ end
|
|
173
217
|
```
|
174
218
|
|
175
219
|
## Javascript Dependency
|
176
|
-
As well as the included ajax_pagination.js file, this gem uses jquery.ba-bbq.js,
|
220
|
+
As well as the included ajax_pagination.js file, this gem uses jquery.ba-bbq.js and jquery.url.js, which are jquery plugins. They are included in the gem as assets already to simplify installation. ajax_pagination.js will automatically require jquery.ba-bbq.js, and jquery.url.js.
|
177
221
|
|
178
|
-
However, if you are already using
|
222
|
+
However, if you are already using them (especially if using a different version), simply ensure that your assets directory contains javascript files of the same name to shadow/override the file in the gem.
|
179
223
|
|
180
224
|
The other javascript dependencies rely on gems: jquery-rails, and jquery-historyjs. So if they are used, AJAX Pagination should play well with other gems using the libraries.
|
181
225
|
|
data/Rakefile
CHANGED
@@ -3,3 +3,19 @@ require "rspec/core/rake_task"
|
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
+
task :travis do
|
7
|
+
serverport = IO.read(File.expand_path("../spec/PORT",__FILE__)).strip # port number that we are using
|
8
|
+
system("cp spec/rails_app/db/development.sqlite3 spec/rails_app/db/test.sqlite3") # take a copy of the development database
|
9
|
+
system("mkdir -p spec/rails_app/vendor/assets/javascripts") # directory to plonk javascripts from dependent gems
|
10
|
+
# obtain jquery javascript assets (this is because sprockets cannot find these files otherwise, when going through nested bundles)
|
11
|
+
# Note that the spec/rails_app/vendor directory is .gitignore because these are generated files
|
12
|
+
system("cp `bundle show jquery-rails`/vendor/assets/javascripts/* spec/rails_app/vendor/assets/javascripts/")
|
13
|
+
system("cp `bundle show jquery-historyjs`/vendor/assets/javascripts/* spec/rails_app/vendor/assets/javascripts/")
|
14
|
+
system("(cd spec/rails_app/ && RAILS_ENV=test bundle exec rails server -d --port=#{serverport})") # daemonized rails server
|
15
|
+
system("bundle exec rake spec")
|
16
|
+
unless $?.exitstatus == 0
|
17
|
+
system("kill -9 `lsof -i :#{serverport} -t`") # kills rails server
|
18
|
+
raise "spec failed!"
|
19
|
+
end
|
20
|
+
system("kill -9 `lsof -i :#{serverport} -t`") # kills rails server
|
21
|
+
end
|
data/ajax_pagination.gemspec
CHANGED
@@ -19,8 +19,11 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
# specify any dependencies here; for example:
|
22
|
-
s.add_development_dependency "
|
23
|
-
|
22
|
+
s.add_development_dependency "rake"
|
23
|
+
s.add_development_dependency "rspec-rails"
|
24
|
+
s.add_development_dependency "sqlite3"
|
25
|
+
s.add_development_dependency "will_paginate"
|
26
|
+
s.add_development_dependency "capybara"
|
24
27
|
|
25
28
|
s.add_runtime_dependency "rails", '>= 3.1'
|
26
29
|
s.add_runtime_dependency "jquery-rails", '>= 1.0'
|
@@ -23,17 +23,66 @@ module AjaxPagination
|
|
23
23
|
# Defaults to "page"
|
24
24
|
#
|
25
25
|
# [:+partial+]
|
26
|
-
# Changes the partial that is returned by this response. Defaults to options [:pagination].
|
26
|
+
# Changes the partial that is returned by this response. Defaults to options [:pagination]. The value can be any object,
|
27
|
+
# and is rendered directly. Therefore, it need not be a string (which renders _page.html.erb for example). Often,
|
28
|
+
# the view to be rendered is not a partial. This is the case if AJAX Pagination is used for menu navigation links.
|
29
|
+
# In this case, each controller action will need to be able to handle AJAX calls and render the full view. To do this,
|
30
|
+
# pass a hash, specifying a file as shown below. That way, a view file without a leading underscore is rendered.
|
31
|
+
#
|
32
|
+
# def welcome
|
33
|
+
# respond_to do |format|
|
34
|
+
# format.html
|
35
|
+
# ajax_pagination format, :pagination => :menu, :partial => {:file => "pages/welcome"}
|
36
|
+
# end
|
37
|
+
# end
|
27
38
|
#
|
28
39
|
def ajax_pagination(format,options = {})
|
29
|
-
if params[:pagination] == (options[:pagination] || 'page')
|
40
|
+
if params[:pagination] == (options[:pagination] || 'page').to_s
|
30
41
|
partial = options[:partial] || params[:pagination]
|
31
|
-
format.js { render :inline => "ajaxPagination
|
42
|
+
format.js { render :inline => "jQuery.ajaxPagination(\"#{params[:pagination]}\",\"#{request.url}\",\"<%= raw escape_javascript(render(partial)) %>\");", :locals => { :partial => partial } }
|
32
43
|
return true
|
33
44
|
else
|
34
45
|
return false
|
35
46
|
end
|
36
47
|
end
|
48
|
+
|
49
|
+
# Tests whether an AJAX Pagination partial might be displayed in the view. If the response is not directly controlled by
|
50
|
+
# AJAX Pagination, it will return true, because the partial might be displayed. The response is handled by AJAX Pagination
|
51
|
+
# if the format is js (javascript), and the params [:pagination] parameter is set. If it is set, then it will return whether
|
52
|
+
# params [:pagination] == pagination (the name of the pagination set, which defaults to page).
|
53
|
+
#
|
54
|
+
# This method is a convenience function so that the controller does not need to perform heavy computation which might only
|
55
|
+
# be required if a certain pagination partial is displayed.
|
56
|
+
#
|
57
|
+
# For example, suppose an index page contains two sets of pagination partials, one for upcoming posts, and one for published
|
58
|
+
# posts, then you might use:
|
59
|
+
#
|
60
|
+
# class PostsController < ApplicationController
|
61
|
+
# def index
|
62
|
+
# if ajax_pagination_displayed? do
|
63
|
+
# @posts = Post.published
|
64
|
+
# @posts.each do |post|
|
65
|
+
# post.heavycomputation
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
# if current_user.is_admin && ajax_pagination_displayed? :upcomingpage do
|
69
|
+
# @upcomingposts = Post.upcoming
|
70
|
+
# @upcomingposts.each do |post|
|
71
|
+
# post.heavycomputation
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
# respond_to do |format|
|
75
|
+
# format.html # index.html.erb
|
76
|
+
# ajax_pagination format
|
77
|
+
# ajax_pagination format, :pagination => 'upcomingpage'
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# The heavy computation will only be performed on posts which will be displayed when AJAX Pagination only wants a partial.
|
83
|
+
def ajax_pagination_displayed?(pagination = :page)
|
84
|
+
(!request.format.js?) || (params[:pagination].nil?) || (params[:pagination] == pagination.to_s)
|
85
|
+
end
|
37
86
|
end
|
38
87
|
end
|
39
88
|
if defined? ActionController
|
@@ -1,3 +1,8 @@
|
|
1
|
+
begin
|
2
|
+
require 'will_paginate' if Gem::Specification.find_by_name('will_paginate') # needed for testing dummy application
|
3
|
+
rescue Gem::LoadError # in case using version without fix for this
|
4
|
+
end
|
5
|
+
|
1
6
|
module AjaxPagination
|
2
7
|
# This module is automatically added to all views, providing helper methods.
|
3
8
|
module HelperAdditions
|
@@ -13,6 +18,23 @@ module AjaxPagination
|
|
13
18
|
#
|
14
19
|
# <%= link_to 'New Comment', new_comment_path %>
|
15
20
|
#
|
21
|
+
# If you prefer to can render yourself, or call another function instead (useful for using this in the
|
22
|
+
# application layout), you can pass in a block. Any content wrapped by the pagination tag will be changed
|
23
|
+
# when paginating. A possible way to use this function by passing a block in an application layout is shown:
|
24
|
+
#
|
25
|
+
# <div class="ajaxpagination menu" data-pagination="menu">
|
26
|
+
# <ul>
|
27
|
+
# <li><%= link_to "Home", root_url %></li>
|
28
|
+
# <li><%= link_to "Posts", posts_url %></li>
|
29
|
+
# <li><%= link_to "Changelog", changelog_url %></li>
|
30
|
+
# <li><%= link_to "Readme", pages_readme_url %></li>
|
31
|
+
# <li><%= link_to "About", pages_about_url %></li>
|
32
|
+
# </ul>
|
33
|
+
# </div>
|
34
|
+
# <%= ajax_pagination :pagination => "menu", :reload => {:urlpart => "path", :urlregex => "^.*$"} do %>
|
35
|
+
# <%= yield %>
|
36
|
+
# <% end %>
|
37
|
+
#
|
16
38
|
# Options:
|
17
39
|
# [:+pagination+]
|
18
40
|
# Changes the pagination name, which is used for requesting new content, and to uniquely identify the
|
@@ -21,7 +43,8 @@ module AjaxPagination
|
|
21
43
|
#
|
22
44
|
# [:+partial+]
|
23
45
|
# Changes the partial which is rendered. Defaults to +options [:pagination]+. The partial should generally
|
24
|
-
# be the same as that given in the controller respond_to block, unless you are doing something strange.
|
46
|
+
# be the same as that given in the controller respond_to block, unless you are doing something strange. If a
|
47
|
+
# block is passed to the function, this option is ignored.
|
25
48
|
#
|
26
49
|
# [:+reload+]
|
27
50
|
# Used to detect whether the partial needs reloading, based on how the url changes. When pagination links are
|
@@ -37,7 +60,11 @@ module AjaxPagination
|
|
37
60
|
# If passed a hash of the form :+urlregex+ => "regularexpression", AJAX Pagination will apply the regular
|
38
61
|
# expression to the url. If a particular subexpression of the match changes, the partial is reloaded. The
|
39
62
|
# subexpression used defaults to the whole match. If the hash includes :+regexindex+ => N, the Nth subexpression
|
40
|
-
# is used.
|
63
|
+
# is used. If the hash also includes :+urlpart+, then the regular expression will only be applied to part of the
|
64
|
+
# url. The part it is applied to depends on the string passed. Allowed strings are any attributes as given at
|
65
|
+
# https://github.com/allmarkedup/jQuery-URL-Parser. Possible attributes include: "source", "protocol", "host",
|
66
|
+
# "port", "relative", "path", "directory", "file", "query". Notice in the above example for the application
|
67
|
+
# layout, how :urlpart => "path" is passed as a reload condition.
|
41
68
|
#
|
42
69
|
# Different parts of the url can be watched for any changes, by passing an array of hashes. For example:
|
43
70
|
#
|
@@ -45,6 +72,10 @@ module AjaxPagination
|
|
45
72
|
#
|
46
73
|
# If nil, AJAX Pagination acts as if it was passed {:query => options [:pagination]}.
|
47
74
|
#
|
75
|
+
# [:+loadzone+]
|
76
|
+
# Instead of using the ajax_pagination_loadzone tag, this option can be set to true. Everything inside this tag
|
77
|
+
# will then be regarded as a loading zone, and the visual loading cues will apply to all the content here.
|
78
|
+
#
|
48
79
|
def ajax_pagination(options = {})
|
49
80
|
pagination = options[:pagination] || 'page' # by default the name of the pagination is 'page'
|
50
81
|
partial = options[:partial] || pagination # default partial rendered is the name of the pagination
|
@@ -56,8 +87,26 @@ module AjaxPagination
|
|
56
87
|
when "Hash", "Array"
|
57
88
|
divoptions["data-reload"] = reload.to_json
|
58
89
|
end
|
90
|
+
if options[:loadzone]
|
91
|
+
divoptions[:class] = "paginated_section paginated_content"
|
92
|
+
divoptions[:style] = "position: relative;"
|
93
|
+
end
|
59
94
|
content_tag :div, divoptions do
|
60
|
-
|
95
|
+
if options[:loadzone]
|
96
|
+
content_tag :div do # for changing the opacity as whole section is a loadzone
|
97
|
+
if block_given?
|
98
|
+
yield
|
99
|
+
else
|
100
|
+
render partial
|
101
|
+
end
|
102
|
+
end
|
103
|
+
else
|
104
|
+
if block_given?
|
105
|
+
yield
|
106
|
+
else
|
107
|
+
render partial
|
108
|
+
end
|
109
|
+
end
|
61
110
|
end
|
62
111
|
end
|
63
112
|
|
@@ -78,7 +127,7 @@ module AjaxPagination
|
|
78
127
|
# <% end %>
|
79
128
|
#
|
80
129
|
def ajax_pagination_loadzone()
|
81
|
-
content_tag :div, :class => "paginated_content", :style => "position: relative" do
|
130
|
+
content_tag :div, :class => "paginated_content", :style => "position: relative;" do
|
82
131
|
content_tag :div do # for changing the opacity
|
83
132
|
yield
|
84
133
|
end
|
Binary file
|
@@ -1,4 +1,5 @@
|
|
1
1
|
//= require jquery.ba-bbq
|
2
|
+
//= require jquery.url
|
2
3
|
|
3
4
|
/*
|
4
5
|
* AJAX Pagination: Ajaxifying your pagination links
|
@@ -8,23 +9,33 @@
|
|
8
9
|
* Distributed under the LGPL license
|
9
10
|
*/
|
10
11
|
if (History && History.enabled) {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
//this.pagination_stack = new Array(); // stack of request urls in history (to get state of url we came from)
|
16
|
-
this.pagination_url = location.href; // url we came from, so we can see transitions of the url
|
12
|
+
jQuery(document).ready(function () {
|
13
|
+
(function( $ ) {
|
14
|
+
var pagination_loader_state = new Array(); // the page we are waiting for
|
15
|
+
var pagination_url = location.href; // url we came from, so we can see transitions of the url
|
17
16
|
|
17
|
+
// semi-public API function - registers new content just loaded to display (if not stale)
|
18
|
+
// not actually public, because it is used by the AJAX Pagination gem itself. However, the other variables/functions should not be accessible by other parts of the gem, whereas this function is accessible by newly loaded scripts.
|
19
|
+
$.ajaxPagination = function(pagination_name,requesturl,content) {
|
20
|
+
if (pagination_loader_state[pagination_name] == requesturl) {
|
21
|
+
//pagination_content_state[pagination_name] = pagination_loader_state[pagination_name];
|
22
|
+
delete pagination_loader_state[pagination_name]; // not waiting for page anymore
|
23
|
+
$("#" + pagination_name + "_paginated_section").html(content);
|
24
|
+
}
|
25
|
+
// else content is stale
|
26
|
+
};
|
18
27
|
function display_pagination_loader(pagination_name) {
|
19
|
-
if (
|
28
|
+
if (pagination_loader_state[pagination_name] != undefined) return; // if already loading, don't reshow loader
|
20
29
|
var paginated_section = $('#' + pagination_name + '_paginated_section');
|
21
|
-
var paginated_content
|
30
|
+
var paginated_content;
|
31
|
+
if (paginated_section.hasClass("paginated_content")) paginated_content = paginated_section; // if the whole section is a loading zone
|
32
|
+
else paginated_content = paginated_section.children(".paginated_content").first(); // don't want to support multiple loader images
|
22
33
|
var height = paginated_content.height();
|
23
34
|
// setup loading look
|
24
35
|
var img = document.createElement("IMG");
|
25
36
|
img.src = "<%= asset_path "ajax-loader.gif" %>";
|
26
37
|
var margin = Math.round(height>400?100:(height/4));
|
27
|
-
$(img).css({'margin': margin + 'px', 'max-height': (height/
|
38
|
+
$(img).css({'margin': margin + 'px', 'max-height': (3*height/4) + 'px'}).addClass('ajaxloader');
|
28
39
|
var div = document.createElement("DIV");
|
29
40
|
$(div).append(img);
|
30
41
|
$(div).css({'position': 'absolute', 'left': 0, 'top': 0, 'width': '100%', 'height': '100%', 'text-align': 'center', 'opacity': 0.9});
|
@@ -36,33 +47,26 @@ if (History && History.enabled) {
|
|
36
47
|
$('body').scrollTop(paginated_section.offset().top);
|
37
48
|
}
|
38
49
|
}
|
39
|
-
|
40
|
-
this.display_pagination_content = function(pagination_name,requesturl,content) {
|
41
|
-
if (this.pagination_loader_state[pagination_name] == requesturl) {
|
42
|
-
//pagination_content_state[pagination_name] = pagination_loader_state[pagination_name];
|
43
|
-
delete this.pagination_loader_state[pagination_name]; // not waiting for page anymore
|
44
|
-
$("#" + pagination_name + "_paginated_section").html(content);
|
45
|
-
}
|
46
|
-
// else content is stale
|
47
|
-
};
|
48
|
-
|
49
50
|
function swapPage(pagination_name,requesturl) { // swaps the page at pagination_name to that from requesturl
|
50
|
-
display_pagination_loader
|
51
|
-
|
51
|
+
display_pagination_loader(pagination_name);
|
52
|
+
pagination_loader_state[pagination_name] = requesturl; // remember which page number we are waiting for
|
52
53
|
$.ajax(requesturl,{dataType:'script',cache:true});
|
53
54
|
}
|
54
55
|
$('body').on("click", ".pagination a, .ajaxpagination a", function() {
|
55
|
-
var
|
56
|
-
|
56
|
+
var pagination_container = $(this).closest(".pagination, .ajaxpagination"); // container of links (use to check for data-pagination first)
|
57
|
+
var pagination_name = pagination_container.data('pagination');
|
58
|
+
if (pagination_name === undefined) pagination_name = /^(.*)_paginated_section$/.exec($(this).closest(".paginated_section").attr("id"))[1]; // if data-pagination not present, search up the tree for a suitable section
|
59
|
+
if ($("#" + pagination_name + "_paginated_section").length != 1) return true; // something wrong, cannot find unique section to load page into
|
60
|
+
if (pagination_name == null) return true; // pagination not set up properly
|
57
61
|
var requesturl = $.param.querystring(this.href,{pagination:pagination_name}); // by default, adds ?pagination=page
|
58
|
-
swapPage
|
59
|
-
|
62
|
+
swapPage(pagination_name,requesturl);
|
63
|
+
pagination_url = this.href;
|
60
64
|
History.pushState(null,document.title,this.href);
|
61
65
|
return false;
|
62
66
|
});
|
63
67
|
|
64
68
|
History.Adapter.bind(window,'popstate',function(){ // popstate, but can work with hash changes as well
|
65
|
-
var from =
|
69
|
+
var from = pagination_url, to = location.href; // from what state to what other state
|
66
70
|
|
67
71
|
$(".paginated_section").each(function(){
|
68
72
|
var pagination_name = /^(.*)_paginated_section$/.exec($(this).attr("id"))[1];
|
@@ -82,10 +86,16 @@ if (History && History.enabled) {
|
|
82
86
|
if ($.deparam.querystring(from)[reload[i].query] !== $.deparam.querystring(to)[reload[i].query]) changed = true;
|
83
87
|
}
|
84
88
|
if (reload[i].urlregex !== undefined) {
|
89
|
+
var fstr = from, tstr = to;
|
90
|
+
if (reload[i].urlpart !== undefined) {
|
91
|
+
fstr = $.url(from).attr(reload[i].urlpart);
|
92
|
+
tstr = $.url(to).attr(reload[i].urlpart);
|
93
|
+
if (typeof(fstr)!="string" || typeof(tstr)!="string") continue; // skip
|
94
|
+
}
|
85
95
|
var index = 0;
|
86
96
|
if (reload[i].regexindex !== undefined) index = reload[i].regexindex;
|
87
97
|
var regex = new RegExp(reload[i].urlregex);
|
88
|
-
var frommatch = regex.exec(
|
98
|
+
var frommatch = regex.exec(fstr), tomatch = regex.exec(tstr);
|
89
99
|
if (frommatch != null && frommatch.length>=index) frommatch = frommatch[index];
|
90
100
|
if (tomatch != null && tomatch.length>=index) tomatch = tomatch[index];
|
91
101
|
if (frommatch !== tomatch) changed = true;
|
@@ -95,14 +105,14 @@ if (History && History.enabled) {
|
|
95
105
|
if (!changed) return; // otherwise it has changed, and we must reload
|
96
106
|
}
|
97
107
|
var requesturl = $.param.querystring(location.href,{pagination:pagination_name}); // by default, adds ?pagination=page
|
98
|
-
swapPage
|
108
|
+
swapPage(pagination_name,requesturl);
|
99
109
|
});
|
100
110
|
|
101
|
-
|
111
|
+
pagination_url = location.href; // update url (new url recognised)
|
102
112
|
});
|
103
113
|
|
104
|
-
|
105
|
-
};
|
114
|
+
History.Adapter.trigger(window,"popstate"); // update stuff on page load
|
115
|
+
})( jQuery );
|
106
116
|
});
|
107
117
|
}
|
108
118
|
|