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.
Files changed (83) hide show
  1. data/.gitignore +3 -0
  2. data/.travis.yml +16 -0
  3. data/CHANGELOG.md +20 -1
  4. data/README.md +49 -5
  5. data/Rakefile +16 -0
  6. data/ajax_pagination.gemspec +5 -2
  7. data/lib/ajax_pagination/controller_additions.rb +52 -3
  8. data/lib/ajax_pagination/helper_additions.rb +53 -4
  9. data/lib/ajax_pagination/version.rb +1 -1
  10. data/lib/assets/images/ajax-loader.gif +0 -0
  11. data/lib/assets/javascripts/ajax_pagination.js.erb +41 -31
  12. data/spec/PORT +1 -0
  13. data/spec/ajax_pagination/controller_additions_spec.rb +79 -0
  14. data/spec/ajax_pagination/helper_additions_spec.rb +45 -0
  15. data/spec/ajax_pagination/integration/ajaxpaginate_spec.rb +33 -0
  16. data/spec/ajax_pagination/integration/nojavascript_spec.rb +30 -0
  17. data/spec/ajax_pagination/integration/paginate_spec.rb +30 -0
  18. data/spec/rails_app/.gitignore +8 -0
  19. data/spec/rails_app/Gemfile +42 -0
  20. data/spec/rails_app/README.rdoc +261 -0
  21. data/spec/rails_app/Rakefile +7 -0
  22. data/spec/rails_app/app/assets/javascripts/application.js +17 -0
  23. data/spec/rails_app/app/assets/javascripts/posts.js +2 -0
  24. data/spec/rails_app/app/assets/stylesheets/application.css +26 -0
  25. data/spec/rails_app/app/assets/stylesheets/posts.css +4 -0
  26. data/spec/rails_app/app/assets/stylesheets/scaffold.css +56 -0
  27. data/spec/rails_app/app/controllers/application_controller.rb +10 -0
  28. data/spec/rails_app/app/controllers/changelog_controller.rb +13 -0
  29. data/spec/rails_app/app/controllers/pages_controller.rb +23 -0
  30. data/spec/rails_app/app/controllers/posts_controller.rb +95 -0
  31. data/spec/rails_app/app/controllers/sessions_controller.rb +11 -0
  32. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  33. data/spec/rails_app/app/helpers/posts_helper.rb +2 -0
  34. data/spec/rails_app/app/mailers/.gitkeep +0 -0
  35. data/spec/rails_app/app/models/.gitkeep +0 -0
  36. data/spec/rails_app/app/models/changelog.rb +19 -0
  37. data/spec/rails_app/app/models/post.rb +4 -0
  38. data/spec/rails_app/app/views/changelog/_page.html.erb +10 -0
  39. data/spec/rails_app/app/views/changelog/index.html.erb +3 -0
  40. data/spec/rails_app/app/views/layouts/application.html.erb +37 -0
  41. data/spec/rails_app/app/views/pages/about.html.erb +4 -0
  42. data/spec/rails_app/app/views/pages/readme.html.erb +4 -0
  43. data/spec/rails_app/app/views/pages/welcome.html.erb +6 -0
  44. data/spec/rails_app/app/views/posts/_form.html.erb +29 -0
  45. data/spec/rails_app/app/views/posts/_page.html.erb +15 -0
  46. data/spec/rails_app/app/views/posts/_upcomingpage.html.erb +15 -0
  47. data/spec/rails_app/app/views/posts/edit.html.erb +6 -0
  48. data/spec/rails_app/app/views/posts/index.html.erb +15 -0
  49. data/spec/rails_app/app/views/posts/new.html.erb +5 -0
  50. data/spec/rails_app/app/views/posts/show.html.erb +13 -0
  51. data/spec/rails_app/config.ru +4 -0
  52. data/spec/rails_app/config/application.rb +56 -0
  53. data/spec/rails_app/config/boot.rb +10 -0
  54. data/spec/rails_app/config/database.yml +25 -0
  55. data/spec/rails_app/config/environment.rb +5 -0
  56. data/spec/rails_app/config/environments/development.rb +37 -0
  57. data/spec/rails_app/config/environments/production.rb +67 -0
  58. data/spec/rails_app/config/environments/test.rb +37 -0
  59. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  60. data/spec/rails_app/config/initializers/inflections.rb +15 -0
  61. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  62. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  63. data/spec/rails_app/config/initializers/session_store.rb +8 -0
  64. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  65. data/spec/rails_app/config/locales/en.yml +5 -0
  66. data/spec/rails_app/config/routes.rb +72 -0
  67. data/spec/rails_app/db/development.sqlite3 +0 -0
  68. data/spec/rails_app/db/migrate/20120219063632_create_posts.rb +10 -0
  69. data/spec/rails_app/db/migrate/20120219130149_add_published_to_post.rb +5 -0
  70. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  71. data/spec/rails_app/log/.gitkeep +0 -0
  72. data/spec/rails_app/public/404.html +26 -0
  73. data/spec/rails_app/public/422.html +26 -0
  74. data/spec/rails_app/public/500.html +25 -0
  75. data/spec/rails_app/public/favicon.ico +0 -0
  76. data/spec/rails_app/script/rails +6 -0
  77. data/spec/rails_app/test/fixtures/posts.yml +9 -0
  78. data/spec/rails_app/test/functional/posts_controller_test.rb +49 -0
  79. data/spec/rails_app/test/unit/helpers/posts_helper_test.rb +4 -0
  80. data/spec/rails_app/test/unit/post_test.rb +7 -0
  81. data/spec/spec_helper.rb +28 -0
  82. data/vendor/assets/javascripts/jquery.url.js +160 -0
  83. metadata +171 -86
data/.gitignore CHANGED
@@ -2,3 +2,6 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ *~
6
+ *.swp
7
+
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". For example:
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 this in the partial (so that the new links get reloaded when the page changes):
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, a jquery plugin. This is included in the gem as an asset already to simplify installation. ajax_pagination.js will automatically require 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 this (especially a different version of this), simply ensure that your file is named jquery.ba-bbq.js as well, so that it overrides the file in the gem.
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
@@ -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 "rspec"
23
- # s.add_runtime_dependency "rest-client"
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.display_pagination_content(\"#{params[:pagination]}\",\"#{request.url}\",\"<%= raw escape_javascript(render(\"#{partial}\")) %>\");" }
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
- render partial
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
@@ -1,3 +1,3 @@
1
1
  module AjaxPagination
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  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
- var ajaxPagination;
12
- $(document).ready(function () {
13
- ajaxPagination = new function() {
14
- this.pagination_loader_state = new Array(); // the page we are waiting for
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 (this.pagination_loader_state[pagination_name] != undefined) return; // if already loading, don't reshow loader
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 = paginated_section.children(".paginated_content").first(); // don't want to support multiple loader images
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/2) + 'px'});
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.call(this,pagination_name);
51
- this.pagination_loader_state[pagination_name] = requesturl; // remember which page number we are waiting for
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 pagination_name = /^(.*)_paginated_section$/.exec($(this).closest(".paginated_section").attr("id"))[1];
56
- if (pagination_name == null) return; // pagination not set up properly
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.call(ajaxPagination,pagination_name,requesturl);
59
- ajaxPagination.pagination_url = this.href;
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 = ajaxPagination.pagination_url, to = location.href; // from what state to what other state
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(from), tomatch = regex.exec(to);
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.call(ajaxPagination,pagination_name,requesturl);
108
+ swapPage(pagination_name,requesturl);
99
109
  });
100
110
 
101
- ajaxPagination.pagination_url = location.href; // update url (new url recognised)
111
+ pagination_url = location.href; // update url (new url recognised)
102
112
  });
103
113
 
104
- //History.Adapter.trigger(window,"popstate"); // update stuff on page load
105
- };
114
+ History.Adapter.trigger(window,"popstate"); // update stuff on page load
115
+ })( jQuery );
106
116
  });
107
117
  }
108
118