ajax_pagination 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## v0.2.0
2
+ **Note: The API has changed slightly from previous versions. If you have used an advanced feature - the :partial option, please use :render now, and if used in a controller, a non-partial template will be used. To use a partial, specify :render => { :partial => "" }.**
3
+
4
+ * Fix jquery_rails dependency, requires jQuery 1.7+
5
+ * rename :partial option to :render in controller_additions methods (all instance and class methods added to ActionController). This is because it now has behaviour like the ActionController render function rather than the ActionView render function
6
+ * change AJAX requests from js to html format. The motivation is to lower barrier to entry, getting AJAX to work. Now, no actual ajax_pagination instance method need be called in the controllers. It is less efficient, and normally not recommended, but not calling it will result in the default template (full page including application layout) to be returned in the AJAX call. AJAX Pagination can then pick out the paginated section required (throwing away everything else).
7
+ * removed all publicly accessible javascript function, there was 1 accessible function for the AJAX result, but it has been removed in favour of the jQuery callback
8
+ * added class method to ActionController which can add AJAX Pagination behaviour to the default_render method. This can be called at the ApplicationController level or for a specific controller. However, this is probably most useful at the application level for AJAX menu navigation (so that ajax_pagination does not need to be called in each controller/action)
9
+ * Warnings added when AJAX Pagination cannot complete AJAX action, or when the setup is suboptimal. This is on only in development mode by default (see gem initializer). These warnings appear as alerts, and are displayed by the javascript code.
10
+ * Initializer generator added, with configuration for an alternative loading image, and warnings setting.
11
+ * renamed data-reload to data-pagination. The new attribute name is already used, but in different circumstances. Note this attribute is only set internally, so usage has not changed. This change should minimise the footprint of AJAX Pagination.
12
+ * updated readme
13
+
1
14
  ## v0.1.0
2
15
  * Added functional tests for controller and helper additions.
3
16
  * Mocked up a rails application using ajax_pagination, at spec/rails_app/. You can run this example application using:
data/README.md CHANGED
@@ -37,7 +37,15 @@ AJAX Pagination depends on jquery-rails and jquery-historyjs, so if their javasc
37
37
  //= require history
38
38
  ```
39
39
 
40
- ## Getting started
40
+ ## Getting Started
41
+ The next section presents the usage of the functions in detail. However, it also presents the different options that can be chosen. For a simpler overview of how you can easily use this gem, please read one of the more specific guides below (found in the wiki):
42
+
43
+ * [Add AJAX to will_paginate](https://github.com/ronalchn/ajax_pagination/wiki/Adding-AJAX-to-will_paginate)
44
+ * [Add AJAX to site navigation](https://github.com/ronalchn/ajax_pagination/wiki/Adding-AJAX-to-site-navigation)
45
+
46
+ and much [more](https://github.com/ronalchn/ajax_pagination/wiki/Home).
47
+
48
+ ## Usage
41
49
 
42
50
  The pagination needs a name (in case you have multiple sets of AJAX pagination on the same webpage). By default, the name is "page". If you only intend to use a single set of pagination links, then leave it as "page". The name is used to distinguish different sets of pagination links, and is also used as a default for other functionaility.
43
51
 
@@ -62,7 +70,7 @@ If the pagination name is not "page", pass the new pagination name in.
62
70
  If the partial is not named the same, pass it the new name as an option:
63
71
 
64
72
  ```erb
65
- <%= ajax_pagination :partial => "mypartial" %>
73
+ <%= ajax_pagination :render => "mypartial" %>
66
74
  ```
67
75
 
68
76
  This will cause it to display content in the _mypartial.* view.
@@ -102,11 +110,17 @@ If the links are outside the partial, you will need to also let AJAX Pagination
102
110
  <% end %>
103
111
  ```
104
112
 
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.
113
+ Incidentally, this example also presents an alternative to passing in a :render 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 :render option is ignored.
106
114
 
107
115
  ### Controller responder
108
116
 
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.
117
+ However, the controller needs to be told how to respond. If we do not indicate the response, it will render the whole html page as usual. This will still work (and only display the new content required), but it will send all the page content. By default, when this happens in development, an alert will pop up warning that this is not the best solution. AJAX Pagination works around this by detecting that you want to load new content into a section called "page" for example, but the new content actually contains a section called "page". Therefore, it replaces the old content with only the content of the response inside the section "page".
118
+
119
+ This behaviour makes it easy to get AJAX Pagination working. And if you are not worried about efficiency (sending all the page content all the time), or if you are doing this for page caching purposes, you can leave it as is. To turn off the warning in development mode, simply generate an initializer, and set ```ruby
120
+ config.warnings = false
121
+ ```.
122
+
123
+ To only send the data that is required (not including the page layout etc.), add a call to <tt>ajax_pagination(format)</tt> in the controller action.
110
124
 
111
125
  ```ruby
112
126
  respond_to do |format|
@@ -115,13 +129,57 @@ respond_to do |format|
115
129
  end
116
130
  ```
117
131
 
118
- If either the pagination name or the partial filename is not the default, you will need to pass these in as options.
132
+ If either the pagination name or the partial filename is not the default (a partial named whatever :pagination is, "_page" in this case), you will need to pass these in as options.
133
+
134
+ ```ruby
135
+ ajax_pagination format, :pagination => "page", :render => "mytemplate"
136
+ ```
137
+
138
+ This will render controller/mytemplate. If you want a partial to be rendered, use:
119
139
 
120
140
  ```ruby
121
- ajax_pagination format, :pagination => "page", :partial => "mypartial"
141
+ ajax_pagination format, :pagination => "page", :render => {:partial => "mytemplate"}
122
142
  ```
123
143
 
124
- The pagination should now work.
144
+ In both cases, the layout is off by default. You can pass in a layout to use in the render by the usual means.
145
+
146
+ The pagination should now be more efficient.
147
+
148
+ ### Default controller responder
149
+
150
+ Although it is fine if used for a single action, eg. with will_paginate, individually adding a respond_to line for every controller and action might take a while, if used for site navigation, or navigating between the different actions of a single controller.
151
+
152
+ There is also a class method defined for ActionController, also named ajax_pagination. If we are using it for site navigation, and the pagination name is "menu", then we can simply call:
153
+
154
+ ```ruby
155
+ class ApplicationController < ActionController:Base
156
+ ajax_pagination :pagination => "menu"
157
+ end
158
+ ```
159
+
160
+ We can, as with the instance method, also pass in a ```ruby
161
+ :render => { :template => "myview", :layout => "mylayout" }
162
+ ``` option. However, in this case, it is actually designed to be used without specifying the view template displayed. The reason is that when it is not defined, the default behaviour is normally what you want. Suppose you accessed a page at the url /controller/action?pagination=menu. The pagination=menu query argument indicates that this is a special AJAX request. If pagination is not defined exactly as "menu" in this example, the rendering does not trigger.
163
+
164
+ AJAX Pagination first tries to render "controller/_menu", :layout => false, if it exists. If it does not, then it will render "controller/action", :layout => false.
165
+
166
+ Therefore, when used for site navigation, it will by default, render the same page it would otherwise have rendered, only without the layout. Sometimes, we have parts of the page we want to render again (and is wrapped by the ajax_pagination container which identifies the section of the page which is reloaded), but exists in the layout. To deal with this case, we can set the layout to a special layout. This is used if, for example, we have flash notices or alerts we want to be removed, or displayed as appropriate for each AJAX call.
167
+
168
+ In this case, we create a layout in layouts/flash_layout.html.erb for example, which renders the flash notices. Then, we can pass the layout in as follows:
169
+
170
+ ```ruby
171
+ class ApplicationController < ActionController:Base
172
+ ajax_pagination :pagination => "menu", :render => { :layout => "flash_layout" }
173
+ end
174
+ ```
175
+
176
+ Notice that no template file is specified. By not specifying the view template file, the controller/action view will be rendered.
177
+
178
+ If we want to navigate within a controller, we can use this in the specific controller instead of the ApplicationController.
179
+
180
+ Please note that the class method only specifies the default behaviour, by defining default_render (but it only triggers on the AJAX calls, otherwise it calls the original default_render function to handle the rendering). This default can be overrided by calling the instance method within an action, allowing you to use this for special cases (controllers or actions).
181
+
182
+ Because the default_render method is used, if you subsequently define default_render, you may clobber the behaviour defined by AJAX Pagination. To deal with this, make sure that the call to the ajax_pagination class method is after any other definition. AJAX Pagination will not clobber any default_render method already defined. Requests which are not AJAX calls will be passed on to the original default_render method.
125
183
 
126
184
  ### Loading visualization
127
185
 
@@ -138,7 +196,7 @@ AJAX Pagination can also add a loading image and partially blanking out of the p
138
196
 
139
197
  Links outside are still clickable (such as the will_paginate links).
140
198
 
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)
199
+ The loading image is currently an image asset at "ajax-loader.gif", so put your loading image there. You can specify a new default filename in your initializer.
142
200
 
143
201
  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
202
 
@@ -181,6 +239,12 @@ Instead of passing in the Array/Hash Ruby object, a string in json form is accep
181
239
  ```erb
182
240
  <%= ajax_pagination :reload => '[{"urlregex":"page=([0-9]+)","regexindex":1},{"query":"page"}]' %>
183
241
  ```
242
+
243
+ ### Initializer
244
+ You can configure AJAX Pagination in the initializer. Run ```
245
+ rails generate ajax_pagination:install
246
+ ``` to get the initializer file.
247
+
184
248
  ## Example Application
185
249
  This gem contains an example application (actually, it is there also for testing purposes), however it is nevertheless a good example.
186
250
 
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_development_dependency "capybara"
27
27
 
28
28
  s.add_runtime_dependency "rails", '>= 3.1'
29
- s.add_runtime_dependency "jquery-rails", '>= 1.0'
29
+ s.add_runtime_dependency "jquery-rails", '>= 1.0.17' # require jQuery 1.7+
30
30
  s.add_runtime_dependency "jquery-historyjs"
31
31
 
32
32
  end
@@ -4,4 +4,16 @@ require "ajax_pagination/helper_additions"
4
4
  require "ajax_pagination/rails"
5
5
 
6
6
  module AjaxPagination
7
+ # default loading image to use
8
+ mattr_accessor :loading_image
9
+ @@loading_image = "ajax-loader.gif"
10
+
11
+ # whether javascript warnings are on, these present themselves as alerts
12
+ mattr_accessor :warnings
13
+ @@warnings = nil # if nil, uses default, which is true only in development mode
14
+
15
+ # run rails generate ajax_pagination:install to create a default initializer with configuration values
16
+ def self.config
17
+ yield self
18
+ end
7
19
  end
@@ -1,7 +1,44 @@
1
1
  module AjaxPagination
2
2
  # This module is automatically added to all controllers
3
3
  module ControllerAdditions
4
- # Registers a javascript format when params [:pagination] matches options [:pagination] ( = "page" by default).
4
+ module ClassMethods
5
+ # Adds default render behaviour for requests with a pagination parameter matching a certain name. By default, this name is the empty string. However, it can be changed.
6
+ # Options:
7
+ # [:+pagination+]
8
+ # The pagination name which should be matched to invoke AJAX Pagination response. Defaults to the empty string "". This is unlike other
9
+ # methods which default to "page". However, this is a better default in this case because this affects more than one controller/action.
10
+ #
11
+ # [:+render+]
12
+ # Overrides default render behaviour for AJAX Pagination, which is to render the partial with name matching the pagination option,
13
+ # or if it does not exist, renders the default template
14
+ #
15
+ def ajax_pagination(options = {});
16
+ # instead of defining default render normally, we save an unbound reference to original function in case it was already defined, since we want to retain the original behaviour, and add to it (if the method is redefined after, this new behaviour is lost, but at least we don't remove others' behaviour - note that this also allows multiple invocations of this with different parameters)
17
+ default_render = self.instance_method(:default_render) # get a reference to original method
18
+ pagination = options[:pagination] || ""
19
+ view = options[:render] || nil
20
+ define_method(:default_render) do |*args|
21
+ if params[:pagination] && params[:pagination] == pagination && request.format == "html" # override if calling AJAX Pagination
22
+ unless view
23
+ if lookup_context.find_all("#{params[:controller]}/_#{params[:pagination]}").any?
24
+ view = { :partial => params[:pagination] } # render partial, layout is off
25
+ else
26
+ view = { :layout => false } # render default view, but turn off layout
27
+ end
28
+ end
29
+ respond_to do |format|
30
+ ajax_pagination format, :pagination => pagination, :render => view
31
+ end
32
+ else # otherwise do what would have been done
33
+ default_render.bind(self).call(*args) # call original method of the same name
34
+ end
35
+ end
36
+ end
37
+ end
38
+ def self.included(base)
39
+ base.extend ClassMethods
40
+ end
41
+ # Registers an ajax response in html format when params [:pagination] matches options [:pagination] ( = "page" by default).
5
42
  # AJAX Pagination uses this response to render only the content which has changed. When this format is triggered,
6
43
  # a partial is passed back, and sent to AJAX Pagination as a function argument in javascript.
7
44
  #
@@ -22,24 +59,31 @@ module AjaxPagination
22
59
  # Changes the pagination name triggering this response. Triggered when params [:pagination] == options [:pagination].
23
60
  # Defaults to "page"
24
61
  #
25
- # [:+partial+]
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.
62
+ # [:+render+]
63
+ # Changes the default template/partial that is rendered by this response. The value can be any object,
64
+ # and is rendered directly. The render behaviour is the same as the render method in controllers. If this option is not used,
65
+ # then the default is a partial of the same name as :pagination, if it exists, otherwise, if it does not,
66
+ # the default template is rendered (ie. the :controller/:action.:format view file). By default, no layout is used
67
+ # to render the template/partial. It can be set by passing in a layout key.
31
68
  #
32
69
  # def welcome
33
70
  # respond_to do |format|
34
71
  # format.html
35
- # ajax_pagination format, :pagination => :menu, :partial => {:file => "pages/welcome"}
72
+ # ajax_pagination format, :pagination => :menu, :render => {:file => "pages/welcome"}
36
73
  # end
37
74
  # end
38
75
  #
39
76
  def ajax_pagination(format,options = {})
40
77
  if params[:pagination] == (options[:pagination] || 'page').to_s
41
- partial = options[:partial] || params[:pagination]
42
- format.js { render :inline => "jQuery.ajaxPagination(\"#{params[:pagination]}\",\"#{request.url}\",\"<%= raw escape_javascript(render(partial)) %>\");", :locals => { :partial => partial } }
78
+ if options[:render]
79
+ view = options[:render] # render non partial
80
+ elsif lookup_context.find_all(params[:controller] + "/_" + params[:pagination]).any?
81
+ view = {:partial => params[:pagination]} # render partial of the same name as pagination
82
+ else # render usual view
83
+ view = {}
84
+ end
85
+ view = { :layout => false }.merge(view); # set default of no layout rendered
86
+ format.html { render view }
43
87
  return true
44
88
  else
45
89
  return false
@@ -48,7 +92,7 @@ module AjaxPagination
48
92
 
49
93
  # Tests whether an AJAX Pagination partial might be displayed in the view. If the response is not directly controlled by
50
94
  # 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
95
+ # if the format is html, and the params [:pagination] parameter is set. If it is set, then it will return whether
52
96
  # params [:pagination] == pagination (the name of the pagination set, which defaults to page).
53
97
  #
54
98
  # This method is a convenience function so that the controller does not need to perform heavy computation which might only
@@ -81,13 +125,8 @@ module AjaxPagination
81
125
  #
82
126
  # The heavy computation will only be performed on posts which will be displayed when AJAX Pagination only wants a partial.
83
127
  def ajax_pagination_displayed?(pagination = :page)
84
- (!request.format.js?) || (params[:pagination].nil?) || (params[:pagination] == pagination.to_s)
128
+ (!request.format.html?) || (params[:pagination].nil?) || (params[:pagination] == pagination.to_s)
85
129
  end
86
130
  end
87
131
  end
88
- if defined? ActionController
89
- ActionController::Base.class_eval do
90
- include AjaxPagination::ControllerAdditions
91
- end
92
- end
93
132
 
@@ -41,10 +41,11 @@ module AjaxPagination
41
41
  # wrapping div tag. The name passed here should be the same as the pagination name used in the controller
42
42
  # respond_to block. Defaults to "page".
43
43
  #
44
- # [:+partial+]
44
+ # [:+render+]
45
45
  # Changes the partial which is rendered. Defaults to +options [:pagination]+. The partial should generally
46
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.
47
+ # block is passed to the function, this option is ignored. You can also pass options instead to render other
48
+ # files, in which case, the behaviour is the same as the render method in views.
48
49
  #
49
50
  # [:+reload+]
50
51
  # Used to detect whether the partial needs reloading, based on how the url changes. When pagination links are
@@ -78,34 +79,24 @@ module AjaxPagination
78
79
  #
79
80
  def ajax_pagination(options = {})
80
81
  pagination = options[:pagination] || 'page' # by default the name of the pagination is 'page'
81
- partial = options[:partial] || pagination # default partial rendered is the name of the pagination
82
+ partial = options[:render] || pagination # default partial rendered is the name of the pagination
82
83
  reload = options[:reload]
83
84
  divoptions = { :id => "#{pagination}_paginated_section", :class => "paginated_section" }
84
85
  case reload.class.to_s
85
86
  when "String"
86
- divoptions["data-reload"] = reload
87
+ divoptions["data-pagination"] = reload
87
88
  when "Hash", "Array"
88
- divoptions["data-reload"] = reload.to_json
89
+ divoptions["data-pagination"] = reload.to_json
89
90
  end
90
91
  if options[:loadzone]
91
92
  divoptions[:class] = "paginated_section paginated_content"
92
93
  divoptions[:style] = "position: relative;"
93
94
  end
94
95
  content_tag :div, divoptions do
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
96
+ if block_given?
97
+ yield
103
98
  else
104
- if block_given?
105
- yield
106
- else
107
- render partial
108
- end
99
+ render partial
109
100
  end
110
101
  end
111
102
  end
@@ -128,16 +119,9 @@ module AjaxPagination
128
119
  #
129
120
  def ajax_pagination_loadzone()
130
121
  content_tag :div, :class => "paginated_content", :style => "position: relative;" do
131
- content_tag :div do # for changing the opacity
132
- yield
133
- end
122
+ yield
134
123
  end
135
124
  end
136
125
  end
137
126
  end
138
- if defined? ActionView
139
- ActionView::Base.class_eval do
140
- include AjaxPagination::HelperAdditions
141
- end
142
- end
143
127
 
@@ -1,4 +1,18 @@
1
1
  module AjaxPagination
2
2
  class Engine < ::Rails::Engine
3
+ initializer 'ajax_pagination.actionpack_additions' do
4
+ ActiveSupport.on_load(:action_controller) do
5
+ include AjaxPagination::ControllerAdditions
6
+ end
7
+ ActiveSupport.on_load(:action_view) do
8
+ include AjaxPagination::HelperAdditions
9
+ end
10
+ end
11
+
12
+ initializer 'ajax_pagination.javascript_warnings' do
13
+ if AjaxPagination.warnings.nil? # if not defined
14
+ AjaxPagination.warnings = Rails.env == 'development' # default setting
15
+ end
16
+ end
3
17
  end
4
18
  end
@@ -1,3 +1,3 @@
1
1
  module AjaxPagination
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -14,16 +14,6 @@ if (History && History.enabled) {
14
14
  var pagination_loader_state = new Array(); // the page we are waiting for
15
15
  var pagination_url = location.href; // url we came from, so we can see transitions of the url
16
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
- };
27
17
  function display_pagination_loader(pagination_name) {
28
18
  if (pagination_loader_state[pagination_name] != undefined) return; // if already loading, don't reshow loader
29
19
  var paginated_section = $('#' + pagination_name + '_paginated_section');
@@ -33,7 +23,7 @@ if (History && History.enabled) {
33
23
  var height = paginated_content.height();
34
24
  // setup loading look
35
25
  var img = document.createElement("IMG");
36
- img.src = "<%= asset_path "ajax-loader.gif" %>";
26
+ img.src = "<%= asset_path AjaxPagination.loading_image %>";
37
27
  var margin = Math.round(height>400?100:(height/4));
38
28
  $(img).css({'margin': margin + 'px', 'max-height': (3*height/4) + 'px'}).addClass('ajaxloader');
39
29
  var div = document.createElement("DIV");
@@ -50,16 +40,48 @@ if (History && History.enabled) {
50
40
  function swapPage(pagination_name,requesturl) { // swaps the page at pagination_name to that from requesturl
51
41
  display_pagination_loader(pagination_name);
52
42
  pagination_loader_state[pagination_name] = requesturl; // remember which page number we are waiting for
53
- $.ajax(requesturl,{dataType:'script',cache:true});
43
+ //$.ajax(requesturl,{dataType:'script',cache:true});
44
+ $.ajax({url: requesturl, data: {pagination:pagination_name},
45
+ dataType: 'html',
46
+ success: function(data) {
47
+ var id = "#" + pagination_name + "_paginated_section"; // element id we are looking for
48
+ // find matching element id in data, after removing script tags
49
+ var content = $("<div>").append(data.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"")).find(id);
50
+ if (content.length>0) {
51
+ $(id).html(content.html());
52
+ <% if AjaxPagination.warnings %>
53
+ alert("AJAX Pagination warning:\nExtra content returned by AJAX request ignored. Only a portion of the page content returned by the server was required. To fix this, explicitly call ajax_pagination for :pagination => \"" + pagination_name + "\" to render only the partial view required. This warning can be turned off in the ajax_pagination initializer file.");
54
+ <% end %>
55
+ }
56
+ else $(id).html(data); // otherwise use all the content
57
+ delete pagination_loader_state[pagination_name]; // not waiting for page anymore
58
+ },
59
+ error: function(jqXHR, textStatus, errorThrown) {
60
+ $(id).html(jqXHR.responseText);
61
+ }
62
+ });
54
63
  }
55
64
  $('body').on("click", ".pagination a, .ajaxpagination a", function() {
56
65
  var pagination_container = $(this).closest(".pagination, .ajaxpagination"); // container of links (use to check for data-pagination first)
57
66
  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
61
- var requesturl = $.param.querystring(this.href,{pagination:pagination_name}); // by default, adds ?pagination=page
62
- swapPage(pagination_name,requesturl);
67
+ if (pagination_name === undefined) {
68
+ pagination_name = /^(.*)_paginated_section$/.exec($(this).closest(".paginated_section").attr("id")); // if data-pagination not present, search up the tree for a suitable section
69
+ if (pagination_name == null) {
70
+ <% if AjaxPagination.warnings %>
71
+ alert("AJAX Pagination warning:\nNo pagination section name given for link, and none could be implicitly assigned, AJAX cancelled for this request");
72
+ <% end %>
73
+ return true; // pagination not set up properly
74
+ }
75
+ pagination_name = pagination_name[1];
76
+ }
77
+ if ($("#" + pagination_name + "_paginated_section").length != 1) { // something wrong, cannot find unique section to load page into
78
+ <% if AjaxPagination.warnings %>
79
+ alert("AJAX Pagination warning:\nExpected one pagination section called " + pagination_name + ", found " + $("#" + pagination_name + "_paginated_section").length);
80
+ <% end %>
81
+ return true; // follow link normally
82
+ }
83
+ //var requesturl = $.param.querystring(this.href,{pagination:pagination_name}); // by default, adds ?pagination=page
84
+ swapPage(pagination_name,this.href);
63
85
  pagination_url = this.href;
64
86
  History.pushState(null,document.title,this.href);
65
87
  return false;
@@ -72,13 +94,13 @@ if (History && History.enabled) {
72
94
  var pagination_name = /^(.*)_paginated_section$/.exec($(this).attr("id"))[1];
73
95
  if (pagination_name == null) return; // pagination not set up properly
74
96
 
75
- // if data-reload is not defined, the use default reload test
76
- if ($(this).data('reload') === undefined) {
97
+ // if data-pagination is not defined, the use default reload test
98
+ if ($(this).data('pagination') === undefined) {
77
99
  // if ?pagination_name=ABC, where ABC is the same for both urls, then don't need to reload
78
100
  if ($.deparam.querystring(from)[pagination_name] === $.deparam.querystring(to)[pagination_name]) return;
79
101
  }
80
102
  else { // otherwise parse json and perform tests
81
- var reload = $(this).data('reload');
103
+ var reload = $(this).data('pagination');
82
104
  if (!(reload instanceof Array)) reload = new Array(reload);
83
105
  var changed = false;
84
106
  for (i=0;i<reload.length;i++) {
@@ -0,0 +1,13 @@
1
+ module AjaxPagination
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates",__FILE__)
5
+
6
+ desc "Creates a Ajax Pagination initializer"
7
+
8
+ def initializer
9
+ template "ajax_pagination.rb", "config/initializers/ajax_pagination.rb"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ AjaxPagination.config do |config|
2
+ # uncomment to change default loading image file, located in assets/images.
3
+ # config.loading_image = "ajax-loader.gif"
4
+
5
+ # whether javascript warnings are on, these present themselves as alerts
6
+ # by default, warnings are active only if the environment is development
7
+ # to configure by environment otherwise, this configuration needs to be added to the environment specific files
8
+ # uncomment to turn warnings on in all environments
9
+ # config.warnings = true
10
+ # or to turn off in all environments
11
+ # config.warnings = false
12
+ end
@@ -2,19 +2,23 @@ require "spec_helper"
2
2
 
3
3
  describe AjaxPagination::ControllerAdditions do
4
4
  def stub_pagination(name)
5
- @controller.stub!(:params).and_return({:pagination => name})
5
+ @controller.stub!(:params).and_return({:pagination => name, :controller => "dummycontroller"})
6
6
  end
7
- def stub_request_format_js(bool)
8
- @controller.stub!(:request).and_return(stub(:format => stub(:js? => bool)))
7
+ def stub_request_format_html(bool)
8
+ @controller.stub!(:request).and_return(stub(:format => stub(:html? => bool)))
9
+ end
10
+ def stub_lookup_context(result)
11
+ @controller.stub!(:lookup_context).and_return(stub(:find_all => result))
9
12
  end
10
13
  before :each do
11
14
  @controller_class = Class.new
12
15
  @controller = @controller_class.new
13
16
  @controller.stub!(:params).and_return({})
14
- stub_request_format_js(false)
17
+ stub_request_format_html(false)
15
18
  @controller_class.send(:include, AjaxPagination::ControllerAdditions)
16
19
  @formatter = Class.new
17
- @formatter.stub!(:js).and_return(0,1,2,3,4,5,6,7,8,9,10) # to detect how many times the function was called
20
+ @formatter.stub!(:html).and_return(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) # to detect how many times the function was called
21
+ stub_lookup_context([]) # no partial matching
18
22
  end
19
23
 
20
24
  describe 'ajax_pagination' do
@@ -23,19 +27,26 @@ describe AjaxPagination::ControllerAdditions do
23
27
  @controller.ajax_pagination(@formatter, :pagination => :page).should be_false
24
28
  @controller.ajax_pagination(@formatter, :pagination => 'page').should be_false
25
29
  @controller.ajax_pagination(@formatter, :pagination => 'page2').should be_false
26
- @formatter.js.should == 0
30
+ @formatter.html.should == 0
27
31
  end
28
32
  it 'should render when pagination parameter matches' do
29
33
  stub_pagination('page')
30
34
  @controller.ajax_pagination(@formatter).should be_true
31
- @formatter.js.should == 1 # detects js function was called once (but checking also calls the function) ...
35
+ @formatter.html.should == 1 # detects html function was called once (but checking also calls the function) ...
32
36
  @controller.ajax_pagination(@formatter, :pagination => :page).should be_true
33
- @formatter.js.should == 3 # ... which is why the next check should be 2 more js function calls
37
+ @formatter.html.should == 3 # ... which is why the next check should be 2 more html function calls
34
38
  @controller.ajax_pagination(@formatter, :pagination => 'page').should be_true
35
- @formatter.js.should == 5
39
+ @formatter.html.should == 5
36
40
  stub_pagination('pageX')
37
41
  @controller.ajax_pagination(@formatter, :pagination => 'pageX').should be_true
38
- @formatter.js.should == 7
42
+ @formatter.html.should == 7
43
+ stub_lookup_context(['matching_partial_found'])
44
+ @controller.ajax_pagination(@formatter, :pagination => 'pageX').should be_true
45
+ @formatter.html.should == 9
46
+ stub_pagination('page')
47
+ @controller.ajax_pagination(@formatter).should be_true
48
+ @formatter.html.should == 11
49
+
39
50
  end
40
51
  it 'should not render when pagination parameter does not match' do
41
52
  stub_pagination('notpage')
@@ -44,20 +55,20 @@ describe AjaxPagination::ControllerAdditions do
44
55
  @controller.ajax_pagination(@formatter, :pagination => 'page').should be_false
45
56
  stub_pagination('notpageX')
46
57
  @controller.ajax_pagination(@formatter, :pagination => 'pageX').should be_false
47
- @formatter.js.should == 0
58
+ @formatter.html.should == 0
48
59
  end
49
60
  end
50
61
 
51
62
  describe 'ajax_pagination_displayed?' do
52
- it 'should display partial when format is not js' do
63
+ it 'should display partial when format is not html' do
53
64
  @controller.ajax_pagination_displayed?.should be_true
54
65
  end
55
- it 'should display partial when format is js but pagination is not defined' do
56
- stub_request_format_js(true)
66
+ it 'should display partial when format is html but pagination is not defined' do
67
+ stub_request_format_html(true)
57
68
  @controller.ajax_pagination_displayed?.should be_true
58
69
  end
59
- it 'should display partial when .js?pagination=pagename' do
60
- stub_request_format_js(true)
70
+ it 'should display partial when .html?pagination=pagename' do
71
+ stub_request_format_html(true)
61
72
  stub_pagination('page')
62
73
  @controller.ajax_pagination_displayed?.should be_true
63
74
  stub_pagination('page2')
@@ -65,8 +76,8 @@ describe AjaxPagination::ControllerAdditions do
65
76
  stub_pagination('page3')
66
77
  @controller.ajax_pagination_displayed?(:page3).should be_true
67
78
  end
68
- it 'should not display partial when .js?pagination!=pagename' do
69
- stub_request_format_js(true)
79
+ it 'should not display partial when .html?pagination!=pagename' do
80
+ stub_request_format_html(true)
70
81
  stub_pagination('notpage')
71
82
  @controller.ajax_pagination_displayed?.should be_false
72
83
  stub_pagination('notpage2')
@@ -20,9 +20,9 @@ describe AjaxPagination::HelperAdditions do
20
20
  @view.should_receive(:render).with('page2')
21
21
  @view.ajax_pagination :pagination => 'page2' # renders the partial named :pagination if :partial not defined
22
22
  @view.should_receive(:render).with('page3')
23
- @view.ajax_pagination :partial => 'page3' # if partial defined, renders partial
23
+ @view.ajax_pagination :render => 'page3' # if partial defined, renders partial
24
24
  @view.should_receive(:render).with('pageX')
25
- @view.ajax_pagination :pagination => 'page10', :partial => 'pageX' # even if pagination also defined as different value
25
+ @view.ajax_pagination :pagination => 'page10', :render => 'pageX' # even if pagination also defined as different value
26
26
  end
27
27
  end
28
28
  describe 'ajax_pagination_loadzone' do
@@ -21,6 +21,7 @@ describe 'paginating with javascript on', :js => true do
21
21
  page.should have_no_selector('.ajaxloader')
22
22
  find('#signin').click
23
23
  visit("http://localhost:#{SERVERPORT}/posts")
24
+ sleep(2)
24
25
  find('#page_paginated_section').find('.next_page').click
25
26
  page.should have_selector('.ajaxloader')
26
27
  sleep(0.5)
@@ -30,4 +31,34 @@ describe 'paginating with javascript on', :js => true do
30
31
  sleep(0.5)
31
32
  page.should have_no_selector('.ajaxloader')
32
33
  end
34
+ it 'shows the configured loading image' do
35
+ visit("http://localhost:#{SERVERPORT}/changelog")
36
+ find('#page_paginated_section').find('.next_page').click
37
+ page.should have_xpath("//img[@class='ajaxloader' and @src = '/assets/myajax-loader.gif']")
38
+ end
39
+ it 'works with browser back and forward buttons' do
40
+ visit("http://localhost:#{SERVERPORT}/changelog")
41
+ find('#page_paginated_section').find('.next_page').click
42
+ sleep(0.5)
43
+ click_link 'About'
44
+ sleep(0.5)
45
+ click_link 'Readme'
46
+ sleep(2)
47
+ page.should have_no_selector('.ajaxloader')
48
+ page.should have_selector('#readmepagetitle')
49
+ page.evaluate_script('window.history.back();') # back to About
50
+ page.should have_selector('.ajaxloader')
51
+ sleep(0.5)
52
+ page.should have_no_selector('.ajaxloader')
53
+ page.should have_selector('#aboutpagetitle')
54
+ page.evaluate_script('window.history.forward();') # forward to readme
55
+ sleep(0.5)
56
+ page.should have_selector('#readmepagetitle')
57
+ page.evaluate_script('window.history.go(-2);') # back to changelog page 2
58
+ sleep(0.5)
59
+ page.should have_no_selector('#aboutpagetitle')
60
+ page.evaluate_script('window.history.forward();') # forward to about
61
+ sleep(0.5)
62
+ page.should have_selector('#aboutpagetitle')
63
+ end
33
64
  end
@@ -39,4 +39,4 @@ gem 'ajax_pagination', :path => "../.."
39
39
  # gem 'capistrano'
40
40
 
41
41
  # To use debugger
42
- # gem 'ruby-debug'
42
+ gem 'ruby-debug'
@@ -1,10 +1,12 @@
1
1
  class ApplicationController < ActionController::Base
2
2
  protect_from_forgery
3
3
  before_filter :slowajaxload
4
-
4
+ ajax_pagination :pagination => 'menu'
5
+ #ajax_pagination :pagination => 'sdf', :partial => {:template => "pages/readme"}
5
6
  def slowajaxload
6
7
  if params[:pagination] && Rails.env == "test"
7
8
  sleep(0.5)
8
9
  end
9
10
  end
11
+
10
12
  end
@@ -7,7 +7,7 @@ class ChangelogController < ApplicationController
7
7
  respond_to do |format|
8
8
  format.html # index.html.erb
9
9
  ajax_pagination(format)
10
- ajax_pagination format, :pagination => :menu, :partial => {:file => "changelog/index"}
10
+ ajax_pagination format, :pagination => :menu
11
11
  end
12
12
  end
13
13
  end
@@ -1,23 +1,21 @@
1
1
  class PagesController < ApplicationController
2
+ respond_to :html, :js, :only => :about
3
+
2
4
  def readme
3
5
  @readme = IO.read(File.expand_path("../../../../../README.md",__FILE__))
4
6
  respond_to do |format|
5
7
  format.html
6
- ajax_pagination format, :pagination => :menu, :partial => {:file => "pages/readme"}
8
+ ajax_pagination format, :pagination => :menu, :render => {:file => "pages/readme"}
7
9
  end
8
10
  end
9
11
 
10
12
  def about
11
- respond_to do |format|
12
- format.html
13
- ajax_pagination format, :pagination => :menu, :partial => {:file => "pages/about"}
14
- end
15
13
  end
16
14
 
17
15
  def welcome
18
16
  respond_to do |format|
19
17
  format.html
20
- ajax_pagination format, :pagination => :menu, :partial => {:file => "pages/welcome"}
18
+ ajax_pagination format, :pagination => :menu
21
19
  end
22
20
  end
23
21
  end
@@ -1,4 +1,5 @@
1
1
  class PostsController < ApplicationController
2
+ ajax_pagination :pagination => 'page'
2
3
  # GET /posts
3
4
  # GET /posts.json
4
5
  def index
@@ -7,9 +8,8 @@ class PostsController < ApplicationController
7
8
  respond_to do |format|
8
9
  format.html # index.html.erb
9
10
  format.json { render :json => @posts }
10
- ajax_pagination(format)
11
11
  ajax_pagination format, :pagination => :upcomingpage
12
- ajax_pagination format, :pagination => :menu, :partial => {:file => "posts/index"}
12
+ ajax_pagination format, :pagination => :menu
13
13
  end
14
14
  end
15
15
 
@@ -17,7 +17,6 @@ class PostsController < ApplicationController
17
17
  # GET /posts/1.json
18
18
  def show
19
19
  @post = Post.find(params[:id])
20
-
21
20
  respond_to do |format|
22
21
  format.html # show.html.erb
23
22
  format.json { render :json => @post }
@@ -0,0 +1,12 @@
1
+ AjaxPagination.config do |config|
2
+ # uncomment to change default loading image file, located in assets/images.
3
+ config.loading_image = "myajax-loader.gif"
4
+
5
+ # whether javascript warnings are on, these present themselves as alerts
6
+ # by default, warnings are active only if the environment is development
7
+ # to configure by environment otherwise, this configuration needs to be added to the environment specific files
8
+ # uncomment to turn warnings on in all environments
9
+ # config.warnings = true
10
+ # or to turn off in all environments
11
+ # config.warnings = false
12
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ajax_pagination
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-20 00:00:00.000000000 Z
12
+ date: 2012-02-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &10548120 !ruby/object:Gem::Requirement
16
+ requirement: &17693300 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *10548120
24
+ version_requirements: *17693300
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec-rails
27
- requirement: &10547700 !ruby/object:Gem::Requirement
27
+ requirement: &17692880 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *10547700
35
+ version_requirements: *17692880
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sqlite3
38
- requirement: &10547260 !ruby/object:Gem::Requirement
38
+ requirement: &17692440 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *10547260
46
+ version_requirements: *17692440
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: will_paginate
49
- requirement: &10546680 !ruby/object:Gem::Requirement
49
+ requirement: &17691880 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *10546680
57
+ version_requirements: *17691880
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: capybara
60
- requirement: &10546160 !ruby/object:Gem::Requirement
60
+ requirement: &17691360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *10546160
68
+ version_requirements: *17691360
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rails
71
- requirement: &10545360 !ruby/object:Gem::Requirement
71
+ requirement: &17690540 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,21 +76,21 @@ dependencies:
76
76
  version: '3.1'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *10545360
79
+ version_requirements: *17690540
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: jquery-rails
82
- requirement: &10575320 !ruby/object:Gem::Requirement
82
+ requirement: &17720620 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
86
86
  - !ruby/object:Gem::Version
87
- version: '1.0'
87
+ version: 1.0.17
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *10575320
90
+ version_requirements: *17720620
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: jquery-historyjs
93
- requirement: &10574740 !ruby/object:Gem::Requirement
93
+ requirement: &17720080 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: '0'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *10574740
101
+ version_requirements: *17720080
102
102
  description: Handles AJAX pagination for you, by hooking up the links you want to
103
103
  load content with javascript in designated page containers. Each webpage can have
104
104
  multiple page containers, each with a different set of pagination links. The page
@@ -127,6 +127,8 @@ files:
127
127
  - lib/ajax_pagination/version.rb
128
128
  - lib/assets/images/ajax-loader.gif
129
129
  - lib/assets/javascripts/ajax_pagination.js.erb
130
+ - lib/generators/ajax_pagination/install_generator.rb
131
+ - lib/generators/templates/ajax_pagination.rb
130
132
  - spec/PORT
131
133
  - spec/ajax_pagination/controller_additions_spec.rb
132
134
  - spec/ajax_pagination/helper_additions_spec.rb
@@ -137,6 +139,7 @@ files:
137
139
  - spec/rails_app/Gemfile
138
140
  - spec/rails_app/README.rdoc
139
141
  - spec/rails_app/Rakefile
142
+ - spec/rails_app/app/assets/images/myajax-loader.gif
140
143
  - spec/rails_app/app/assets/javascripts/application.js
141
144
  - spec/rails_app/app/assets/javascripts/posts.js
142
145
  - spec/rails_app/app/assets/stylesheets/application.css
@@ -174,6 +177,7 @@ files:
174
177
  - spec/rails_app/config/environments/development.rb
175
178
  - spec/rails_app/config/environments/production.rb
176
179
  - spec/rails_app/config/environments/test.rb
180
+ - spec/rails_app/config/initializers/ajax_pagination.rb
177
181
  - spec/rails_app/config/initializers/backtrace_silencers.rb
178
182
  - spec/rails_app/config/initializers/inflections.rb
179
183
  - spec/rails_app/config/initializers/mime_types.rb