neat-pages 0.1.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +1 -1
  6. data/README.md +58 -22
  7. data/app/assets/javascripts/neat_pages/base.coffee +8 -1
  8. data/lib/.reek +12 -0
  9. data/lib/neat-pages.rb +2 -1
  10. data/lib/neat_pages/base.rb +5 -7
  11. data/lib/neat_pages/engine.rb +3 -1
  12. data/lib/neat_pages/errors.rb +9 -0
  13. data/lib/neat_pages/helpers.rb +8 -10
  14. data/lib/neat_pages/helpers/builder.rb +26 -16
  15. data/lib/neat_pages/helpers/navigation.rb +39 -27
  16. data/lib/neat_pages/helpers/status.rb +14 -0
  17. data/lib/neat_pages/implants/action_controller_implant.rb +3 -0
  18. data/lib/neat_pages/implants/mongoid_implant.rb +12 -10
  19. data/lib/neat_pages/{implants/railtie.rb → railtie.rb} +7 -4
  20. data/neat-pages.gemspec +23 -0
  21. data/spec/controllers/application_controller_spec.rb +24 -0
  22. data/spec/dummy/Rakefile +6 -0
  23. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  24. data/spec/dummy/app/controllers/examples_controller.rb +11 -0
  25. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  26. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  27. data/spec/dummy/bin/bundle +3 -0
  28. data/spec/dummy/bin/rails +4 -0
  29. data/spec/dummy/bin/rake +4 -0
  30. data/spec/dummy/config.ru +4 -0
  31. data/spec/dummy/config/application.rb +18 -0
  32. data/spec/dummy/config/boot.rb +5 -0
  33. data/spec/dummy/config/database.yml +5 -0
  34. data/spec/dummy/config/environment.rb +5 -0
  35. data/spec/dummy/config/environments/development.rb +29 -0
  36. data/spec/dummy/config/environments/production.rb +80 -0
  37. data/spec/dummy/config/environments/test.rb +36 -0
  38. data/spec/dummy/config/initializers/standard_rails_initializers.rb +9 -0
  39. data/spec/dummy/config/locales/en.yml +5 -0
  40. data/spec/dummy/config/routes.rb +3 -0
  41. data/spec/dummy/db/test.sqlite3 +0 -0
  42. data/spec/neat_pages/base_spec.rb +31 -5
  43. data/spec/neat_pages/helpers/builder_spec.rb +109 -0
  44. data/spec/neat_pages/helpers/navigation_spec.rb +105 -0
  45. data/spec/neat_pages/helpers/status_spec.rb +65 -0
  46. data/spec/neat_pages/helpers_spec.rb +67 -0
  47. data/spec/neat_pages/implants/mongoid_implant_spec.rb +43 -0
  48. data/spec/spec_helper.rb +21 -6
  49. data/spec/support/views_helper.rb +16 -0
  50. data/vendor/assets/javascripts/jquery.hashchange.min.js +1 -1
  51. metadata +134 -42
  52. data/lib/neat_pages/implants.rb +0 -12
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 59f1070651e4d23adb8f0301c9da861318a9383c
4
+ data.tar.gz: 84d03414625e89ae07971611b489c3ef39ea2ce7
5
+ SHA512:
6
+ metadata.gz: ed1ab0e93b1510b1cf8a0be03b3e5efa7d1c5b368dc8601916f116265a4aca0845ddb9de1d079fdcd956b48c3dcbac0e1c92dec9f091528d211557b992ba455f
7
+ data.tar.gz: fc131f2eed332101da8a660a4288d66a2c4147e8eb52addda5d039a2464203c87c4237c1fe37d28a645166121814627307270b6e01810a30dfcc46e2786cd785
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ .bundle
3
+ .metrics
4
+ .rspec
5
+ Gemfile.lock
6
+ coverage/*
7
+ pkg/*
8
+ spec/dummy/log
9
+ tmp/*
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in neat-pages.gemspec
4
4
  gemspec
5
+
6
+ gem 'coveralls', require: false
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 De Marque inc.
1
+ Copyright (c) 2013 De Marque inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
4
 
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- Neat Pages [![Build Status](https://secure.travis-ci.org/demarque/neat-pages.png?branch=master)](http://travis-ci.org/demarque/neat-pages)
1
+ Neat Pages [![Build Status](https://secure.travis-ci.org/alchimikweb/neat-pages.png?branch=master)](http://travis-ci.org/alchimikweb/neat-pages) [![Code Climate](https://codeclimate.com/github/alchimikweb/neat-pages.png)](https://codeclimate.com/github/alchimikweb/neat-pages) [![Coverage Status](https://coveralls.io/repos/alchimikweb/neat-pages/badge.png)](https://coveralls.io/r/alchimikweb/neat-pages)
2
2
  ===============
3
3
 
4
- A simple pagination API to paginate Mongoid Models.
4
+ A simple pagination API to paginate Mongoid models.
5
5
 
6
6
  Install
7
7
  -------
@@ -10,10 +10,7 @@ Install
10
10
  gem install neat-pages
11
11
  ```
12
12
 
13
- Rails 3
14
- -------
15
-
16
- In your Gemfile:
13
+ or add the following line to Gemfile:
17
14
 
18
15
  ```ruby
19
16
  gem 'neat-pages'
@@ -29,7 +26,7 @@ In your css manifest put : ``` require neat_pages ```
29
26
 
30
27
  In your javascript manifest put : ``` require neat_pages ```
31
28
 
32
- You only need to require the javascript if you use the AJAX functionnality.
29
+ You only need to require the javascript if you use the AJAX functionality.
33
30
 
34
31
  That's it.
35
32
 
@@ -37,15 +34,11 @@ That's it.
37
34
  Usage
38
35
  -----
39
36
 
40
-
41
- Examples
42
- --------
43
-
44
37
  ### Minimal integration
45
38
 
46
- In your controller *(app/controllers/products_controller.rb)*
47
-
48
39
  ```ruby
40
+ # app/controllers/products_controller.rb
41
+
49
42
  def index
50
43
  paginate
51
44
 
@@ -53,29 +46,29 @@ In your controller *(app/controllers/products_controller.rb)*
53
46
  end
54
47
  ```
55
48
 
56
- In your view *(app/views/products/index.html.erb)*
57
-
58
49
  ```erb
50
+ <%# app/views/products/index.html.erb %>
51
+
59
52
  <%= render 'products', products: @products %>
60
53
  <%= neat_pages_navigation %>
61
54
  ```
62
55
 
63
56
 
64
- ### Summon the power of AJAX
65
-
66
- In your controller *(app/controllers/products_controller.rb)*
57
+ ### Summon the power of AJAX pagination
67
58
 
68
59
  ```ruby
60
+ # app/controllers/products_controller.rb
61
+
69
62
  def index
70
- paginate
63
+ paginate per_page: 50 # Default is 20
71
64
 
72
65
  @products = Product.all.paginate(pagination)
73
66
  end
74
67
  ```
75
68
 
76
- In your view *(app/views/products/index.html.erb)*
77
-
78
69
  ```erb
70
+ <%# app/views/products/index.html.erb %>
71
+
79
72
  <%= neat_pages_ajax_items 'products', products: @products %>
80
73
  <%= neat_pages_navigation %>
81
74
  ```
@@ -83,10 +76,53 @@ In your view *(app/views/products/index.html.erb)*
83
76
  Create the file *app/views/products/index.neatpage.erb* and place the following code in it.
84
77
 
85
78
  ```erb
79
+ <%# app/views/products/index.neatpage.erb %>
80
+
86
81
  <% self.formats = ["html"] %>
87
82
  <%= render 'products', products: @products %>
88
83
  ```
89
- ### Events
84
+
85
+ ### Automatically paginate your Web Services
86
+
87
+ For every request that called the method ```paginate```, the header's response will contain the following data :
88
+
89
+ ```
90
+ X-Total-Items=200;
91
+ X-Total-Pages=20;
92
+ X-Per-Page=10;
93
+ X-Current-Page=3;
94
+ ```
95
+
96
+ ### Out of Bound
97
+
98
+ If the page requested is out of bound, the controller method ```render_out_of_bound``` will be called.
99
+ This method will render the text 'out_of_bound' with a status 404. If you want, you can override it like this :
100
+
101
+
102
+ ```ruby
103
+ # app/controllers/application_controller.rb
104
+
105
+ def render_out_of_bound
106
+ render text: 'My custom code', status: 404
107
+ end
108
+ ```
109
+
110
+ ### Helper Methods
111
+
112
+ ```neat_pages_ajax_items(partial_path, options={})```
113
+
114
+ Activate the ajax pagination. See the previous example.
115
+
116
+
117
+ ``` neat_pages_navigation ```
118
+
119
+ Generate a page navigation. (ex: < 1 2 3 4 >)
120
+
121
+ ``` neat_pages_status ```
122
+
123
+ Generate the current state of the pagination (ex: 30 to 40 / 200)
124
+
125
+ ### Javascript Events
90
126
 
91
127
  #### `neat_pages:update`
92
128
 
@@ -12,7 +12,14 @@ class NeatPage
12
12
  $('#neat-pages-navigation li.page a').click (e) => @thatPage $(e.target) ; return false
13
13
 
14
14
 
15
- buildURL: (noPage) -> encodeURI(@getPage(noPage).attr('href').replace('?', '.neatpage?'))
15
+ buildURL: (noPage) ->
16
+ url = @getPage(noPage).attr('href')
17
+
18
+ if window.location.pathname is '/' or window.location.pathname is ''
19
+ encodeURI(url + '&format=neatpage')
20
+ else
21
+ encodeURI(url.replace('?', '.neatpage?'))
22
+
16
23
 
17
24
  cachePage: (noPage) -> $.get(@buildURL(noPage), (data) => @cachePages[noPage] = data)
18
25
 
@@ -0,0 +1,12 @@
1
+ ---
2
+ DuplicateMethodCall:
3
+ allow_calls: ['options', 'params']
4
+ max_calls: 3
5
+ IrresponsibleModule:
6
+ enabled: false
7
+ TooManyStatements:
8
+ max_statements: 10
9
+ UncommunicativeMethodName:
10
+ enabled: false
11
+ UncommunicativeVariableName:
12
+ enabled: false
@@ -5,5 +5,6 @@ end
5
5
  require "neat_pages/engine"
6
6
  require 'neat_pages/base'
7
7
  require 'neat_pages/errors'
8
- require 'neat_pages/implants'
8
+ require 'neat_pages/railtie'
9
+
9
10
 
@@ -10,13 +10,13 @@ module NeatPages
10
10
  #*************************************************************************************
11
11
  # CONSTRUCTOR
12
12
  #*************************************************************************************
13
- def initialize(current_page, options={})
13
+ def initialize(current_page_param, options={})
14
14
  options = { per_page: 10, total_items: 0 }.merge(options)
15
15
 
16
16
  @per_page = options[:per_page].to_i
17
17
  @total_items = options[:total_items]
18
18
 
19
- @current_page = init_current_page(current_page)
19
+ init_current_page current_page_param
20
20
 
21
21
  @out_of_bound = init_out_of_bound
22
22
  end
@@ -89,11 +89,9 @@ module NeatPages
89
89
  #*************************************************************************************
90
90
  # PRIVATE INSTANCE METHODS
91
91
  #*************************************************************************************
92
- def init_current_page(current_page)
93
- current_page = current_page.to_i
94
- current_page = 1 if current_page == 0
95
-
96
- return current_page
92
+ def init_current_page(current_page_param)
93
+ @current_page = current_page_param.to_i
94
+ @current_page = 1 if @current_page == 0
97
95
  end
98
96
 
99
97
  def init_out_of_bound
@@ -1,5 +1,7 @@
1
1
  module NeatPages
2
+ #*************************************************************************************
3
+ # Make the gem behave as an engine.
4
+ #*************************************************************************************
2
5
  class Engine < Rails::Engine
3
- #auto wire
4
6
  end
5
7
  end
@@ -1,4 +1,13 @@
1
1
  module NeatPages
2
+ #*************************************************************************************
3
+ # Error that will be raised if the page called is out of bound.
4
+ #*************************************************************************************
2
5
  class OutOfBound < StandardError
3
6
  end
7
+
8
+ #*************************************************************************************
9
+ # Error that will be raised if the pagination isn't initialized
10
+ #*************************************************************************************
11
+ class Uninitalized < StandardError
12
+ end
4
13
  end
@@ -1,22 +1,20 @@
1
+ #*************************************************************************************
2
+ # Insert a bunch of helper methods in the ActionView::Base of a Rails project.
3
+ #*************************************************************************************
1
4
  module NeatPages::Helpers
2
5
  def neat_pages_ajax_items(partial_path, options={})
3
- ('<div id="neat-pages-ajax-wrapper" class="first-load">' + render(partial_path, options) + '</div>').html_safe
4
- end
5
-
6
- def neat_pages_base_url
7
- "#{request.protocol}#{request.host}#{request.port == 80 ? '' : ':' + request.port.to_s}#{request.path_info}"
8
- end
6
+ options = { wrapper: :div }.merge(options)
9
7
 
10
- def neat_pages_base_params
11
- request.env['action_dispatch.request.query_parameters']
8
+ ("<#{options[:wrapper]} id=\"neat-pages-ajax-wrapper\" class=\"first-load\">" + render(partial_path, options) + "</#{options[:wrapper]}>").html_safe
12
9
  end
13
10
 
11
+ # DEPRECATED : The options parameter is deprecated. I left it here for backward compatibility. (2013-11-20)
14
12
  def neat_pages_navigation(options={})
15
- NeatPages::Helpers::Navigation.new(pagination, neat_pages_base_url, neat_pages_base_params).generate(options)
13
+ NeatPages::Helpers::Navigation.new(pagination, request).generate
16
14
  end
17
15
 
18
16
  def neat_pages_status
19
- NeatPages::Helpers::Status.new(pagination, neat_pages_base_url, neat_pages_base_params).generate
17
+ NeatPages::Helpers::Status.new(pagination, request).generate
20
18
  end
21
19
 
22
20
  ::ActionView::Base.send :include, self
@@ -1,27 +1,40 @@
1
+ #*************************************************************************************
2
+ # Builder will help build a string of html output.
3
+ #*************************************************************************************
1
4
  class NeatPages::Helpers::Builder
2
- def initialize(pagination, base_url, params)
5
+ attr_reader :pagination
6
+
7
+ delegate :per_page, to: :pagination
8
+ delegate :total_items, to: :pagination
9
+
10
+ def initialize(pagination, request)
3
11
  @pagination = pagination
4
- @base_url = base_url
5
- @params = params
12
+ @base_url = generate_base_url_from_request(request)
13
+ @params = request.env['action_dispatch.request.query_parameters']
6
14
  @params.delete('utf8')
15
+
7
16
  reset_builder
8
17
  end
9
18
 
10
19
  def b(str='')
11
20
  @builder << str
12
21
 
13
- return @builder.html_safe
22
+ @builder.html_safe
14
23
  end
15
24
 
16
- def li(content, css_class='', hidden=false)
17
- attributes = 'class="' + css_class + '" '
18
- attributes << 'style="display:none"' if hidden
25
+ def li(content, css_class='', options={})
26
+ options = { hidden: false }.merge(options)
27
+
28
+ attributes = ' class="' + css_class + '"' if not css_class.empty?
29
+ attributes << ' style="display:none"' if options[:hidden]
19
30
 
20
- return "<li #{attributes}>#{content}</li>"
31
+ b "<li#{attributes}>#{content}</li>"
21
32
  end
22
33
 
23
34
  def path_to(page)
24
- return @base_url + '?' + @params.map { |k,v| "#{k}=#{v}"}.join('&') + "&page=#{page}"
35
+ qs = @params.map { |k,v| "#{k}=#{v}" if k != 'page' }.compact.join('&')
36
+
37
+ "#{@base_url}?#{qs}" + (qs.empty? ? '' : '&') + "page=#{page}"
25
38
  end
26
39
 
27
40
  def reset_builder
@@ -32,12 +45,9 @@ class NeatPages::Helpers::Builder
32
45
  (defined? I18n) ? I18n.t("neat_pages.#{text_path}") : text_path
33
46
  end
34
47
 
35
- def method_missing(*args, &block)
36
- if @pagination.respond_to? args.first
37
- return @pagination.send *args, &block
38
- else
39
- raise NoMethodError.new("undefined local variable or method '#{args.first}' for #{self.class}")
40
- end
41
- end
48
+ private
42
49
 
50
+ def generate_base_url_from_request(request)
51
+ "#{request.protocol}#{request.host}#{request.port == 80 ? '' : ':' + request.port.to_s}#{request.path_info}"
52
+ end
43
53
  end
@@ -1,15 +1,25 @@
1
+ #*************************************************************************************
2
+ # Navigation take care of generating the html code for the pagination navigation.
3
+ #
4
+ # Output Example
5
+ #
6
+ # < Previous | 1 | 2 | 3 | Next >
7
+ #*************************************************************************************
1
8
  class NeatPages::Helpers::Navigation < NeatPages::Helpers::Builder
2
- def generate(options={})
3
- options = { format: :standard }.merge(options)
4
-
9
+ delegate :current_page, to: :pagination
10
+ delegate :next?, to: :pagination
11
+ delegate :next_page, to: :pagination
12
+ delegate :paginated?, to: :pagination
13
+ delegate :previous?, to: :pagination
14
+ delegate :previous_page, to: :pagination
15
+ delegate :total_pages, to: :pagination
16
+
17
+ def generate
5
18
  return '' if not paginated?
6
19
 
7
20
  reset_builder
8
21
 
9
- return case options[:format]
10
- when :light then navigation_light
11
- else navigation_standard
12
- end
22
+ navigation_standard
13
23
  end
14
24
 
15
25
  private
@@ -17,9 +27,11 @@ class NeatPages::Helpers::Navigation < NeatPages::Helpers::Builder
17
27
  def link_to(label, no_page, options={})
18
28
  options = { class: '' }.merge(options)
19
29
 
20
- url = (no_page == '#' ? '#' : path_to(no_page))
30
+ attributes = { "data-page" => no_page }
31
+ attributes["href"] = (no_page == '#' ? '#' : path_to(no_page))
32
+ attributes["class"] = options[:class] if not options[:class].blank?
21
33
 
22
- return "<a href=\"#{url}\" data-page=\"#{no_page}\" class=\"#{options[:class]}\">#{label}</a>"
34
+ return "<a " + attributes.map{ |k,v| "#{k}=\"#{v}\"" }.join(" ") + ">#{label}</a>"
23
35
  end
24
36
 
25
37
  def link_to_page(no_page)
@@ -44,17 +56,7 @@ class NeatPages::Helpers::Navigation < NeatPages::Helpers::Builder
44
56
  list_class = enabled ? '' : 'disabled'
45
57
  content = enabled ? navigation_link(direction) : link_to(navigation_label(direction), '#', class: direction)
46
58
 
47
- b li(content, "move #{direction} #{list_class}")
48
- end
49
-
50
- def navigation_light
51
- b '<ul class="light" ' + navigation_attributes + '>'
52
- navigation_list_link 'previous', previous?
53
- navigation_page_items(10)
54
- navigation_list_link 'next', next?
55
- b '</ul>'
56
-
57
- return b
59
+ li(content, "move #{direction} #{list_class}")
58
60
  end
59
61
 
60
62
  def navigation_link(direction)
@@ -62,16 +64,15 @@ class NeatPages::Helpers::Navigation < NeatPages::Helpers::Builder
62
64
  end
63
65
 
64
66
  def navigation_page_items(nbr_items=10)
65
- half_nbr_items = nbr_items / 2
66
-
67
- start = current_page > half_nbr_items ? (current_page - half_nbr_items + 1) : 1
68
- finish = current_page >= total_pages - half_nbr_items ? total_pages : (start + nbr_items - 1)
69
- start = (finish - nbr_items + 1) if start - finish < nbr_items
70
- start = 1 if start < 1
67
+ start, finish = get_bounds_of_pages nbr_items
71
68
 
72
69
  (1..total_pages).each do |i|
73
70
  hidden = (i < start or i > finish)
74
- b (current_page == i ? li(link_to_page(i), 'page selected') : li(link_to_page(i), 'page', hidden))
71
+ if current_page == i
72
+ li link_to_page(i), 'page selected'
73
+ else
74
+ li link_to_page(i), 'page', hidden: hidden
75
+ end
75
76
  end
76
77
  end
77
78
 
@@ -85,4 +86,15 @@ class NeatPages::Helpers::Navigation < NeatPages::Helpers::Builder
85
86
  return b
86
87
  end
87
88
 
89
+ def get_bounds_of_pages(nbr_items)
90
+ half_nbr_items = nbr_items / 2
91
+
92
+ start = current_page > half_nbr_items ? (current_page - half_nbr_items + 1) : 1
93
+ finish = current_page >= total_pages - half_nbr_items ? total_pages : (start + nbr_items - 1)
94
+ start = (finish - nbr_items + 1) if start - finish < nbr_items
95
+ start = 1 if start < 1
96
+
97
+ return [start, finish]
98
+ end
99
+
88
100
  end