neat-pages 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +79 -3
- data/Rakefile +1 -1
- data/app/assets/javascripts/neat_pages/base.coffee +138 -0
- data/app/assets/javascripts/neat_pages/index.js +3 -0
- data/app/assets/stylesheets/neat_pages/base.css.scss +24 -0
- data/app/assets/stylesheets/neat_pages/index.css +3 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/fr.yml +4 -0
- data/lib/neat-pages.rb +2 -1
- data/lib/neat_pages/base.rb +1 -15
- data/lib/neat_pages/engine.rb +5 -0
- data/lib/neat_pages/helpers.rb +21 -69
- data/lib/neat_pages/helpers/builder.rb +47 -0
- data/lib/neat_pages/helpers/navigation.rb +88 -0
- data/lib/neat_pages/helpers/status.rb +30 -0
- data/lib/neat_pages/implants/action_controller_implant.rb +7 -14
- data/lib/neat_pages/implants/railtie.rb +11 -2
- data/spec/neat_pages/base_spec.rb +23 -23
- data/spec/spec_helper.rb +1 -0
- data/vendor/assets/javascripts/jquery.hashchange.min.js +9 -0
- metadata +37 -15
- data/spec/neat_pages/helpers_spec.rb +0 -29
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Neat Pages [](http://travis-ci.org/demarque/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
|
-------
|
@@ -19,13 +19,89 @@ In your Gemfile:
|
|
19
19
|
gem 'neat-pages'
|
20
20
|
```
|
21
21
|
|
22
|
+
|
23
|
+
Setup
|
24
|
+
-----
|
25
|
+
|
26
|
+
First you need to link the assets.
|
27
|
+
|
28
|
+
In your css manifest put : ``` require neat_pages ```
|
29
|
+
|
30
|
+
In your javascript manifest put : ``` require neat_pages ```
|
31
|
+
|
32
|
+
You only need to require the javascript if you use the AJAX functionnality.
|
33
|
+
|
34
|
+
That's it.
|
35
|
+
|
36
|
+
|
22
37
|
Usage
|
23
38
|
-----
|
24
39
|
|
25
|
-
|
40
|
+
|
41
|
+
Examples
|
42
|
+
--------
|
43
|
+
|
44
|
+
### Minimal integration
|
45
|
+
|
46
|
+
In your controller *(app/controllers/products_controller.rb)*
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
def index
|
50
|
+
paginate
|
51
|
+
|
52
|
+
@products = Product.all.paginate(pagination)
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
In your view *(app/views/products/index.html.erb)*
|
57
|
+
|
58
|
+
```erb
|
59
|
+
<%= render 'products', products: @products %>
|
60
|
+
<%= neat_pages_navigation %>
|
61
|
+
```
|
62
|
+
|
63
|
+
|
64
|
+
### Summon the power of AJAX
|
65
|
+
|
66
|
+
In your controller *(app/controllers/products_controller.rb)*
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
def index
|
70
|
+
paginate
|
71
|
+
|
72
|
+
@products = Product.all.paginate(pagination)
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
In your view *(app/views/products/index.html.erb)*
|
77
|
+
|
78
|
+
```erb
|
79
|
+
<%= neat_pages_ajax_items 'products', products: @products %>
|
80
|
+
<%= neat_pages_navigation %>
|
81
|
+
```
|
82
|
+
|
83
|
+
Create the file *app/views/products/index.neatpage.erb* and place the following code in it.
|
84
|
+
|
85
|
+
```erb
|
86
|
+
<% self.formats = ["html"] %>
|
87
|
+
<%= render 'products', products: @products %>
|
88
|
+
```
|
89
|
+
|
90
|
+
|
91
|
+
Locales
|
92
|
+
-------
|
93
|
+
|
94
|
+
If you want to translate the text in the pagination helpers, just add the following keys in i18n.
|
95
|
+
|
96
|
+
```yml
|
97
|
+
fr:
|
98
|
+
neat_pages:
|
99
|
+
next_page: Page suivante
|
100
|
+
previous_page: Page précédente
|
101
|
+
```
|
26
102
|
|
27
103
|
|
28
104
|
Copyright
|
29
105
|
---------
|
30
106
|
|
31
|
-
Copyright (c)
|
107
|
+
Copyright (c) 2013 De Marque inc. See LICENSE for further details.
|
data/Rakefile
CHANGED
@@ -0,0 +1,138 @@
|
|
1
|
+
class NeatPage
|
2
|
+
constructor: () ->
|
3
|
+
@initPagination()
|
4
|
+
|
5
|
+
$(window).hashchange () => @loadPage @getPageFromHash()
|
6
|
+
|
7
|
+
$('#neat-pages-navigation li.next a').click (e) => @nextPage() ; return false
|
8
|
+
$('#neat-pages-navigation li.previous a').click (e) => @previousPage() ; return false
|
9
|
+
$('#neat-pages-navigation li.page a').click (e) => @thatPage $(e.target) ; return false
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
cachePage: (noPage) ->
|
14
|
+
url = @getPage(noPage).attr('href').replace('?', '.neatpage?')
|
15
|
+
$.get(url, (data) => @cachePages[noPage] = data)
|
16
|
+
|
17
|
+
|
18
|
+
cacheNextPage: () ->
|
19
|
+
noNextPage = @getPageFromHash() + 1
|
20
|
+
|
21
|
+
@cachePage noNextPage if noNextPage < @totalPages() and not @pageIsCached noNextPage
|
22
|
+
|
23
|
+
|
24
|
+
centerPages: () ->
|
25
|
+
current = @currentPageNumber()
|
26
|
+
totalPageLink = $('#neat-pages-navigation li.page:visible').length
|
27
|
+
halfTotalPageLink = totalPageLink/2
|
28
|
+
|
29
|
+
start = if current > halfTotalPageLink then current - halfTotalPageLink + 1 else 1
|
30
|
+
finish = if current >= @totalPages() - halfTotalPageLink then @totalPages() else (start + totalPageLink - 1)
|
31
|
+
start = (finish - totalPageLink + 1) if start - finish < totalPageLink - 1
|
32
|
+
start = 1 if start < 1
|
33
|
+
|
34
|
+
$('#neat-pages-navigation li.page').hide()
|
35
|
+
@getPage(page).closest('li').show() for page in [start..finish]
|
36
|
+
|
37
|
+
|
38
|
+
currentPage: () -> $('#neat-pages-navigation li.page.selected a')
|
39
|
+
|
40
|
+
currentPageNumber: () -> Number(@currentPage().data('page'))
|
41
|
+
|
42
|
+
getPage: (noPage) -> $('#neat-pages-navigation li.page a[data-page="' + noPage + '"]')
|
43
|
+
|
44
|
+
getPageFromHash: () ->
|
45
|
+
page = 1
|
46
|
+
|
47
|
+
if location.hash.indexOf('page-') isnt -1
|
48
|
+
selection = Number(location.hash.replace('#page-', ''))
|
49
|
+
page = selection if selection > 0 and selection <= @totalPages()
|
50
|
+
|
51
|
+
return page
|
52
|
+
|
53
|
+
|
54
|
+
initPagination: () ->
|
55
|
+
@cachePages = []
|
56
|
+
@cachePages[@currentPageNumber()] = $('#neat-pages-ajax-wrapper').html()
|
57
|
+
@cacheNextPage()
|
58
|
+
|
59
|
+
# When starting from a page that is not 1. (EX: Press Refresh or Back)
|
60
|
+
if @getPageFromHash() != 1
|
61
|
+
$('#neat-pages-ajax-wrapper').hide()
|
62
|
+
@loadPage @getPageFromHash()
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
loadPage: (noPage) ->
|
67
|
+
$('#neat-pages-ajax-wrapper').css( opacity: 0.5 )
|
68
|
+
@updateNav Number(noPage)
|
69
|
+
@updateStatus()
|
70
|
+
|
71
|
+
if @pageIsCached noPage
|
72
|
+
@updatePage @cachePages[noPage], noPage
|
73
|
+
else
|
74
|
+
url = @getPage(noPage).attr('href').replace('?', '.neatpage?')
|
75
|
+
$.get(url, (data) => @updatePage data, noPage)
|
76
|
+
|
77
|
+
|
78
|
+
moveIsDisabled: (direction) -> $('#neat-pages-navigation li.' + direction).hasClass('disabled')
|
79
|
+
|
80
|
+
nextPage: () -> @updateHash @currentPageNumber() + 1 if not @moveIsDisabled 'next'
|
81
|
+
|
82
|
+
pageIsCached: (noPage) -> if @cachePages[noPage] then true else false
|
83
|
+
|
84
|
+
perPage: () -> Number($('#neat-pages-navigation').data('per-page'))
|
85
|
+
|
86
|
+
previousPage: () -> @updateHash @currentPageNumber() - 1 if not @moveIsDisabled 'previous'
|
87
|
+
|
88
|
+
thatPage: (link) -> @updateHash link.data('page') if not link.closest('li').hasClass('selected')
|
89
|
+
|
90
|
+
totalItems: () -> Number($('#neat-pages-navigation').data('total-items'))
|
91
|
+
|
92
|
+
totalPages: () -> Number($('#neat-pages-navigation').data('total-pages'))
|
93
|
+
|
94
|
+
updateHash: (noPage) -> location.href = '#page-' + noPage
|
95
|
+
|
96
|
+
updateNav: (noPage) ->
|
97
|
+
$('#neat-pages-navigation li.page').removeClass('selected')
|
98
|
+
@getPage(noPage).closest('li').addClass('selected')
|
99
|
+
$('#neat-pages-navigation li.move').removeClass('disabled')
|
100
|
+
|
101
|
+
if noPage <= 1
|
102
|
+
$('#neat-pages-navigation li.previous').addClass('disabled')
|
103
|
+
$('#neat-pages-navigation li.previous a').attr('href', '#')
|
104
|
+
else
|
105
|
+
$('#neat-pages-navigation li.previous a').attr('href', @getPage(noPage-1).attr('href'))
|
106
|
+
|
107
|
+
if noPage >= @totalPages()
|
108
|
+
$('#neat-pages-navigation li.next').addClass('disabled')
|
109
|
+
$('#neat-pages-navigation li.next a').attr('href', '#')
|
110
|
+
else
|
111
|
+
$('#neat-pages-navigation li.next a').attr('href', @getPage(noPage+1).attr('href'))
|
112
|
+
|
113
|
+
@centerPages()
|
114
|
+
|
115
|
+
|
116
|
+
updatePage: (data, noPage) ->
|
117
|
+
@cachePages[noPage] = data if not @pageIsCached noPage
|
118
|
+
|
119
|
+
$('#neat-pages-ajax-wrapper').hide()
|
120
|
+
$('#neat-pages-ajax-wrapper').css( opacity: 1 )
|
121
|
+
$('#neat-pages-ajax-wrapper').html(data)
|
122
|
+
$('#neat-pages-ajax-wrapper').fadeIn(300)
|
123
|
+
|
124
|
+
$('#neat-pages-navigation').trigger 'change'
|
125
|
+
|
126
|
+
@cacheNextPage()
|
127
|
+
|
128
|
+
|
129
|
+
updateStatus: () ->
|
130
|
+
from = ((@currentPageNumber()-1) * @perPage()) + 1
|
131
|
+
to = from + @perPage() - 1
|
132
|
+
to = @totalItems if to > @totalItems()
|
133
|
+
|
134
|
+
$('#neat-pages-status').find('span.from').html(from)
|
135
|
+
$('#neat-pages-status').find('span.to').html(to)
|
136
|
+
|
137
|
+
|
138
|
+
$ -> new NeatPage if $('#neat-pages-navigation').length > 0
|
@@ -0,0 +1,24 @@
|
|
1
|
+
/****************************************************************************
|
2
|
+
* STANDARD
|
3
|
+
****************************************************************************/
|
4
|
+
ul#neat-pages-navigation{border-top:1px solid #ddd;clear:both;padding-top:30px;text-align:center;width:100%;
|
5
|
+
li{background:none;border:0;display:inline-block;font-size:12px;margin:0px 2px 0px 0px;
|
6
|
+
a{background:#fff;border:solid 1px #eee;color:#555;font-size:12px;font-weight:normal;margin-right:2px;padding:5px 9px;text-decoration:none;}
|
7
|
+
a:hover{border:solid 1px #ccc;color:#000;}
|
8
|
+
}
|
9
|
+
li.page.selected a{background:#ccc;border:1px solid #777;color:#222;font-weight:normal;padding:5px 9px;}
|
10
|
+
li.move.disabled a{background-color:#eee;border:solid 1px #DEDEDE;color:#aaa;cursor:default;}
|
11
|
+
}
|
12
|
+
|
13
|
+
/****************************************************************************
|
14
|
+
* LIGHT
|
15
|
+
****************************************************************************/
|
16
|
+
ul#neat-pages-navigation.light{
|
17
|
+
li.page{display:none;float:left;height:1px;position:absolute;visibility:hidden;width:1px;}
|
18
|
+
li.move{display:block;}
|
19
|
+
li.move.disabled{display:none;}
|
20
|
+
li.move.previous{float:left;margin-left:5%;}
|
21
|
+
li.move.next{float:right;margin-right:5%;}
|
22
|
+
}
|
23
|
+
|
24
|
+
|
data/lib/neat-pages.rb
CHANGED
data/lib/neat_pages/base.rb
CHANGED
@@ -11,7 +11,7 @@ module NeatPages
|
|
11
11
|
# CONSTRUCTOR
|
12
12
|
#*************************************************************************************
|
13
13
|
def initialize(current_page, options={})
|
14
|
-
options = { :
|
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]
|
@@ -25,24 +25,10 @@ module NeatPages
|
|
25
25
|
#*************************************************************************************
|
26
26
|
# PUBLIC INSTANCE METHODS
|
27
27
|
#*************************************************************************************
|
28
|
-
def activate_helpers(base_url='', params={})
|
29
|
-
@helpers = NeatPages::Helpers.new(self, base_url, params)
|
30
|
-
end
|
31
|
-
|
32
28
|
def empty?
|
33
29
|
@total_items == 0
|
34
30
|
end
|
35
31
|
|
36
|
-
def helpers
|
37
|
-
if @helpers
|
38
|
-
@helpers
|
39
|
-
else
|
40
|
-
raise 'You must activate the helpers by calling "activate_helpers".'
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
alias_method :h, :helpers
|
45
|
-
|
46
32
|
def limit
|
47
33
|
@per_page
|
48
34
|
end
|
data/lib/neat_pages/helpers.rb
CHANGED
@@ -1,75 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#*************************************************************************************
|
6
|
-
class Helpers
|
7
|
-
#*************************************************************************************
|
8
|
-
# CONSTRUCTOR
|
9
|
-
#*************************************************************************************
|
10
|
-
def initialize(pagination, base_url, params)
|
11
|
-
@pagination = pagination
|
12
|
-
@base_url = base_url
|
13
|
-
@params = params
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
#*************************************************************************************
|
18
|
-
# PUBLIC INSTANCE METHODS
|
19
|
-
#*************************************************************************************
|
20
|
-
def navigation
|
21
|
-
if paginated?
|
22
|
-
content = ''
|
23
|
-
content << navigation_link('previous') if previous?
|
24
|
-
content << navigation_link('next') if next?
|
25
|
-
|
26
|
-
return "<div class=\"pagination\">#{content.html_safe}</div>".html_safe
|
27
|
-
else
|
28
|
-
return ''
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def status
|
33
|
-
return '' if empty? or out_of_bound?
|
34
|
-
|
35
|
-
from = offset
|
36
|
-
to = from + per_page
|
37
|
-
to = total_items if to > total_items
|
38
|
-
|
39
|
-
return "#{from+1} #{t('to')} #{to}/#{total_items}"
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
#*************************************************************************************
|
45
|
-
# PRIVATE INSTANCE METHODS
|
46
|
-
#*************************************************************************************
|
47
|
-
def navigation_link(direction)
|
48
|
-
label_str = direction == 'next' ? "#{t('page_next')} »" : "« #{t('page_previous')}"
|
49
|
-
|
50
|
-
link_url = path_to(send("#{direction}_page"))
|
51
|
-
|
52
|
-
return "<a href=\"#{link_url}\" class=\"#{direction}\">#{label_str}</a>".html_safe
|
53
|
-
end
|
54
|
-
|
55
|
-
def path_to(page)
|
56
|
-
qs = ["page=#{page}"]
|
1
|
+
module NeatPages::Helpers
|
2
|
+
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
|
57
5
|
|
58
|
-
|
6
|
+
def neat_pages_base_url
|
7
|
+
request.protocol + request.host + request.path_info
|
8
|
+
end
|
59
9
|
|
60
|
-
|
61
|
-
|
10
|
+
def neat_pages_base_params
|
11
|
+
request.env['action_dispatch.request.query_parameters']
|
12
|
+
end
|
62
13
|
|
63
|
-
|
64
|
-
|
65
|
-
|
14
|
+
def neat_pages_navigation(options={})
|
15
|
+
NeatPages::Helpers::Navigation.new(pagination, neat_pages_base_url, neat_pages_base_params).generate(options)
|
16
|
+
end
|
66
17
|
|
67
|
-
|
68
|
-
|
69
|
-
return @pagination.send *args, &block
|
70
|
-
else
|
71
|
-
raise NoMethodError.new("undefined local variable or method '#{args.first}' for #{self.class}")
|
72
|
-
end
|
73
|
-
end
|
18
|
+
def neat_pages_status
|
19
|
+
NeatPages::Helpers::Status.new(pagination, neat_pages_base_url, neat_pages_base_params).generate
|
74
20
|
end
|
21
|
+
|
22
|
+
::ActionView::Base.send :include, self
|
75
23
|
end
|
24
|
+
|
25
|
+
require 'neat_pages/helpers/builder'
|
26
|
+
require 'neat_pages/helpers/navigation'
|
27
|
+
require 'neat_pages/helpers/status'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class NeatPages::Helpers::Builder
|
2
|
+
def initialize(pagination, base_url, params)
|
3
|
+
@pagination = pagination
|
4
|
+
@base_url = base_url
|
5
|
+
@params = params
|
6
|
+
|
7
|
+
reset_builder
|
8
|
+
end
|
9
|
+
|
10
|
+
def b(str='')
|
11
|
+
@builder << str
|
12
|
+
|
13
|
+
return @builder.html_safe
|
14
|
+
end
|
15
|
+
|
16
|
+
def li(content, css_class='', hidden=false)
|
17
|
+
attributes = 'class="' + css_class + '" '
|
18
|
+
attributes << 'style="display:none"' if hidden
|
19
|
+
|
20
|
+
return "<li #{attributes}>#{content}</li>"
|
21
|
+
end
|
22
|
+
|
23
|
+
def path_to(page)
|
24
|
+
qs = ["page=#{page}"]
|
25
|
+
|
26
|
+
@params.each { |k,v| qs << "#{k}=#{v}" if k != 'page' }
|
27
|
+
|
28
|
+
return @base_url + '?' + qs.join("&")
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset_builder
|
32
|
+
@builder = ''
|
33
|
+
end
|
34
|
+
|
35
|
+
def t(text_path)
|
36
|
+
(defined? I18n) ? I18n.t("neat_pages.#{text_path}") : text_path
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(*args, &block)
|
40
|
+
if @pagination.respond_to? args.first
|
41
|
+
return @pagination.send *args, &block
|
42
|
+
else
|
43
|
+
raise NoMethodError.new("undefined local variable or method '#{args.first}' for #{self.class}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class NeatPages::Helpers::Navigation < NeatPages::Helpers::Builder
|
2
|
+
def generate(options={})
|
3
|
+
options = { format: :standard }.merge(options)
|
4
|
+
|
5
|
+
return '' if not paginated?
|
6
|
+
|
7
|
+
reset_builder
|
8
|
+
|
9
|
+
return case options[:format]
|
10
|
+
when :light then navigation_light
|
11
|
+
else navigation_standard
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def link_to(label, no_page, options={})
|
18
|
+
options = { class: '' }.merge(options)
|
19
|
+
|
20
|
+
url = (no_page == '#' ? '#' : path_to(no_page))
|
21
|
+
|
22
|
+
return "<a href=\"#{url}\" data-page=\"#{no_page}\" class=\"#{options[:class]}\">#{label}</a>"
|
23
|
+
end
|
24
|
+
|
25
|
+
def link_to_page(no_page)
|
26
|
+
link_to no_page, no_page
|
27
|
+
end
|
28
|
+
|
29
|
+
def navigation_attributes
|
30
|
+
{
|
31
|
+
"id" => "neat-pages-navigation",
|
32
|
+
"data-neat-pages-control=" => "navigation",
|
33
|
+
"data-per-page" => per_page,
|
34
|
+
"data-total-items" => total_items,
|
35
|
+
"data-total-pages" => total_pages
|
36
|
+
}.map{ |k,v| "#{k}=\"#{v}\"" }.join(' ')
|
37
|
+
end
|
38
|
+
|
39
|
+
def navigation_label(direction)
|
40
|
+
(direction == 'next' ? "#{t('next_page')} »" : "« #{t('previous_page')}").html_safe
|
41
|
+
end
|
42
|
+
|
43
|
+
def navigation_list_link(direction, enabled)
|
44
|
+
list_class = enabled ? '' : 'disabled'
|
45
|
+
content = enabled ? navigation_link(direction) : link_to(navigation_label(direction), '#', class: direction)
|
46
|
+
|
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
|
58
|
+
end
|
59
|
+
|
60
|
+
def navigation_link(direction)
|
61
|
+
link_to(navigation_label(direction), send("#{direction}_page"), class: direction)
|
62
|
+
end
|
63
|
+
|
64
|
+
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
|
71
|
+
|
72
|
+
(1..total_pages).each do |i|
|
73
|
+
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))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def navigation_standard
|
79
|
+
b '<ul class="standard" ' + navigation_attributes + '>'
|
80
|
+
navigation_list_link 'previous', previous?
|
81
|
+
navigation_page_items(10)
|
82
|
+
navigation_list_link 'next', next?
|
83
|
+
b '</ul>'
|
84
|
+
|
85
|
+
return b
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class NeatPages::Helpers::Status < NeatPages::Helpers::Builder
|
2
|
+
def generate
|
3
|
+
return '' if empty? or out_of_bound?
|
4
|
+
|
5
|
+
from, to = get_from_to_data
|
6
|
+
|
7
|
+
return build_status from, to
|
8
|
+
end
|
9
|
+
|
10
|
+
def build_status(from, to)
|
11
|
+
reset_builder
|
12
|
+
|
13
|
+
b '<span data-neat-pages-control="status" id="neat-pages-status">'
|
14
|
+
b "<span class=\"from\">#{from+1}</span>"
|
15
|
+
b " #{t('to')} "
|
16
|
+
b "<span class=\"to\">#{to}</span>/"
|
17
|
+
b "<span class=\"total\">#{total_items}</span>"
|
18
|
+
b '</span>'
|
19
|
+
|
20
|
+
return b
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_from_to_data
|
24
|
+
from = offset
|
25
|
+
to = from + per_page
|
26
|
+
to = total_items if to > total_items
|
27
|
+
|
28
|
+
return [from, to]
|
29
|
+
end
|
30
|
+
end
|
@@ -3,31 +3,24 @@ module NeatPages::Implants::ActionControllerImplant
|
|
3
3
|
|
4
4
|
included do
|
5
5
|
append_after_filter :set_pagination_header
|
6
|
-
helper_method :pagination, :pagination_helpers
|
7
|
-
rescue_from NeatPages::OutOfBound, :with => :render_out_of_bound
|
8
|
-
end
|
9
6
|
|
10
|
-
|
11
|
-
options.reverse_merge!(:per_page => 20)
|
7
|
+
helper_method :pagination
|
12
8
|
|
13
|
-
|
9
|
+
rescue_from NeatPages::OutOfBound, with: :render_out_of_bound
|
10
|
+
end
|
14
11
|
|
15
|
-
|
16
|
-
|
12
|
+
def paginate(options={})
|
13
|
+
options.reverse_merge! per_page: 20
|
17
14
|
|
18
|
-
@_env['neat_pages'] =
|
15
|
+
@_env['neat_pages'] = NeatPages::Base.new(params[:page], options)
|
19
16
|
end
|
20
17
|
|
21
18
|
def pagination
|
22
19
|
@_env['neat_pages']
|
23
20
|
end
|
24
21
|
|
25
|
-
def pagination_helpers
|
26
|
-
pagination.helpers
|
27
|
-
end
|
28
|
-
|
29
22
|
def render_out_of_bound
|
30
|
-
render :
|
23
|
+
render text: "out_of_bound", status: 404
|
31
24
|
end
|
32
25
|
|
33
26
|
def set_pagination_header
|
@@ -2,12 +2,21 @@ require 'neat_pages/implants/action_controller_implant'
|
|
2
2
|
|
3
3
|
module NeatPages::Implants
|
4
4
|
class Railtie < Rails::Railtie
|
5
|
-
initializer "
|
6
|
-
|
5
|
+
initializer "neat-pages" do |app|
|
7
6
|
ActiveSupport.on_load :action_controller do
|
8
7
|
include NeatPages::Implants::ActionControllerImplant
|
9
8
|
end
|
10
9
|
|
10
|
+
ActiveSupport.on_load :action_view do
|
11
|
+
require 'neat_pages/helpers'
|
12
|
+
end
|
13
|
+
|
14
|
+
Mime::Type.register "text/html", :neatpage if not Mime::Type.lookup_by_extension :neatpage
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
18
|
+
|
19
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
20
|
+
|
21
|
+
I18n.load_path << File.join(dir, '../../../config/locales', 'fr.yml')
|
22
|
+
|
@@ -6,7 +6,7 @@ describe NeatPages::Base do
|
|
6
6
|
#*************************************************************************************
|
7
7
|
describe "#empty?" do
|
8
8
|
context "with a 20 items pagination" do
|
9
|
-
specify { NeatPages::Base.new(0, :
|
9
|
+
specify { NeatPages::Base.new(0, total_items: 20).should_not be_empty }
|
10
10
|
end
|
11
11
|
|
12
12
|
context "with a 0 item pagination" do
|
@@ -16,109 +16,109 @@ describe NeatPages::Base do
|
|
16
16
|
|
17
17
|
describe "#next_page" do
|
18
18
|
context "with a 100 items pagination starting at 0 and having 10 items per page" do
|
19
|
-
specify { NeatPages::Base.new(0, :
|
19
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 100).next_page.should eql 2 }
|
20
20
|
end
|
21
21
|
|
22
22
|
context "with a 100 items pagination starting at page 3 and having 15 items per page" do
|
23
|
-
specify { NeatPages::Base.new(3, :
|
23
|
+
specify { NeatPages::Base.new(3, per_page: 15, total_items: 100).next_page.should eql 4 }
|
24
24
|
end
|
25
25
|
|
26
26
|
context "with a 5 items pagination starting at 0 and having 10 items per page" do
|
27
|
-
specify { NeatPages::Base.new(0, :
|
27
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 5).next_page.should eql 1 }
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
describe "#next?" do
|
32
32
|
context "with a 100 items pagination starting at 0 and having 10 items per page" do
|
33
|
-
specify { NeatPages::Base.new(0, :
|
33
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 100).should be_next }
|
34
34
|
end
|
35
35
|
|
36
36
|
context "with a 5 items pagination starting at 0 and having 10 items per page" do
|
37
|
-
specify { NeatPages::Base.new(0, :
|
37
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 5).should_not be_next }
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
describe "#offset" do
|
42
42
|
context "with a 100 items pagination starting at page 1 and having 10 items per page" do
|
43
|
-
specify { NeatPages::Base.new(1, :
|
43
|
+
specify { NeatPages::Base.new(1, per_page: 10, total_items: 100).offset.should eql 0 }
|
44
44
|
end
|
45
45
|
|
46
46
|
context "with a 100 items pagination starting at page 4 and having 15 items per page" do
|
47
|
-
specify { NeatPages::Base.new(4, :
|
47
|
+
specify { NeatPages::Base.new(4, per_page: 15, total_items: 100).offset.should eql 45 }
|
48
48
|
end
|
49
49
|
|
50
50
|
context "with a 100 items pagination starting at page 999 and having 15 items per page" do
|
51
|
-
specify { NeatPages::Base.new(999, :
|
51
|
+
specify { NeatPages::Base.new(999, per_page: 15, total_items: 100).offset.should eql 101 }
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
55
|
describe "#out_of_bound?" do
|
56
56
|
context "with a 100 items pagination starting at page 1 and having 10 items per page" do
|
57
|
-
specify { NeatPages::Base.new(1, :
|
57
|
+
specify { NeatPages::Base.new(1, per_page: 10, total_items: 100).should_not be_out_of_bound }
|
58
58
|
end
|
59
59
|
|
60
60
|
context "with a 100 items pagination starting at page 11 and having 10 items per page" do
|
61
|
-
specify { NeatPages::Base.new(11, :
|
61
|
+
specify { NeatPages::Base.new(11, per_page: 10, total_items: 100).should be_out_of_bound }
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
describe "#previous_page" do
|
66
66
|
context "with a 100 items pagination starting at page 5 and having 10 items per page" do
|
67
|
-
specify { NeatPages::Base.new(5, :
|
67
|
+
specify { NeatPages::Base.new(5, per_page: 10, total_items: 100).previous_page.should eql 4 }
|
68
68
|
end
|
69
69
|
|
70
70
|
context "with a 100 items pagination starting at page 3 and having 15 items per page" do
|
71
|
-
specify { NeatPages::Base.new(3, :
|
71
|
+
specify { NeatPages::Base.new(3, per_page: 15, total_items: 100).previous_page.should eql 2 }
|
72
72
|
end
|
73
73
|
|
74
74
|
context "with a 50 items pagination starting at 0 and having 10 items per page" do
|
75
|
-
specify { NeatPages::Base.new(0, :
|
75
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 50).previous_page.should eql 1 }
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
79
|
describe "#previous" do
|
80
80
|
context "with a 100 items pagination starting at page 5 and having 10 items per page" do
|
81
|
-
specify { NeatPages::Base.new(5, :
|
81
|
+
specify { NeatPages::Base.new(5, per_page: 10, total_items: 100).should be_previous }
|
82
82
|
end
|
83
83
|
|
84
84
|
context "with a 50 items pagination starting at 0 and having 10 items per page" do
|
85
|
-
specify { NeatPages::Base.new(0, :
|
85
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 50).should_not be_previous }
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
89
|
describe "#previous?" do
|
90
90
|
context "with a 100 items pagination starting at 0 and having 10 items per page" do
|
91
|
-
specify { NeatPages::Base.new(0, :
|
91
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 100).should_not be_previous }
|
92
92
|
end
|
93
93
|
|
94
94
|
context "with a 100 items pagination starting at page 2 and having 10 items per page" do
|
95
|
-
specify { NeatPages::Base.new(2, :
|
95
|
+
specify { NeatPages::Base.new(2, per_page: 10, total_items: 100).should be_previous }
|
96
96
|
end
|
97
97
|
|
98
98
|
context "with a 5 items pagination starting at 0 and having 10 items per page" do
|
99
|
-
specify { NeatPages::Base.new(0, :
|
99
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 5).should_not be_previous }
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
103
|
describe "#response_headers" do
|
104
104
|
context "with a 200 items pagination starting at page 1 and having 10 items per page" do
|
105
|
-
subject { NeatPages::Base.new(1, :
|
105
|
+
subject { NeatPages::Base.new(1, per_page: 10, total_items: 200).response_headers }
|
106
106
|
|
107
107
|
its(:length) { should eql 4 }
|
108
108
|
its(['X-Total-Items']) { should eql '200' }
|
109
109
|
its(['X-Total-Pages']) { should eql '20' }
|
110
|
-
its(['X-Per-Page']) { should eql '10' }
|
110
|
+
its(['X-Per-Page']) { should eql '10' }#
|
111
111
|
its(['X-Current-Page']) { should eql '1' }
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
115
|
describe "#total_pages" do
|
116
116
|
context "with a 100 items pagination and having 10 items per page" do
|
117
|
-
specify { NeatPages::Base.new(0, :
|
117
|
+
specify { NeatPages::Base.new(0, per_page: 10, total_items: 100).total_pages.should eql 10 }
|
118
118
|
end
|
119
119
|
|
120
120
|
context "with a 0 items pagination and having 10 items per page" do
|
121
|
-
specify { NeatPages::Base.new(0, :
|
121
|
+
specify { NeatPages::Base.new(0, per_page: 10).total_pages.should eql 1 }
|
122
122
|
end
|
123
123
|
end
|
124
124
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery hashchange event - v1.3 - 7/21/2010
|
3
|
+
* http://benalman.com/projects/jquery-hashchange-plugin/
|
4
|
+
*
|
5
|
+
* Copyright (c) 2010 "Cowboy" Ben Alman
|
6
|
+
* Dual licensed under the MIT and GPL licenses.
|
7
|
+
* http://benalman.com/about/license/
|
8
|
+
*/
|
9
|
+
(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){r||l(a());n()}).attr("src",r||"javascript:0").insertAfter("body")[0].contentWindow;h.onpropertychange=function(){try{if(event.propertyName==="title"){q.document.title=h.title}}catch(s){}}}};j.stop=k;o=function(){return a(q.location.href)};l=function(v,s){var u=q.document,t=$.fn[c].domain;if(v!==s){u.title=h.title;u.open();t&&u.write('<script>document.domain="'+t+'"<\/script>');u.close();q.location.hash=v}}})();return j})()})(jQuery,this);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neat-pages
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,30 +9,41 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
|
16
|
-
requirement: &2151882000 !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
15
|
+
requirement: &2159931860 !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
17
|
- - ! '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 0.8.7
|
22
|
-
|
20
|
+
none: false
|
23
21
|
prerelease: false
|
24
|
-
|
22
|
+
type: :development
|
23
|
+
name: rake
|
24
|
+
version_requirements: *2159931860
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
|
27
|
-
requirement: &2151880820 !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
26
|
+
requirement: &2159930740 !ruby/object:Gem::Requirement
|
29
27
|
requirements:
|
30
28
|
- - ! '>='
|
31
29
|
- !ruby/object:Gem::Version
|
32
30
|
version: '2.0'
|
31
|
+
none: false
|
32
|
+
prerelease: false
|
33
33
|
type: :development
|
34
|
+
name: rspec
|
35
|
+
version_requirements: *2159930740
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
requirement: &2159929800 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '3.0'
|
42
|
+
none: false
|
34
43
|
prerelease: false
|
35
|
-
|
44
|
+
type: :development
|
45
|
+
name: rails
|
46
|
+
version_requirements: *2159929800
|
36
47
|
description: ''
|
37
48
|
email:
|
38
49
|
- sebastien@demarque.com
|
@@ -42,9 +53,19 @@ extra_rdoc_files:
|
|
42
53
|
- LICENSE
|
43
54
|
- README.md
|
44
55
|
files:
|
56
|
+
- app/assets/javascripts/neat_pages/base.coffee
|
57
|
+
- app/assets/javascripts/neat_pages/index.js
|
58
|
+
- app/assets/stylesheets/neat_pages/base.css.scss
|
59
|
+
- app/assets/stylesheets/neat_pages/index.css
|
60
|
+
- config/locales/en.yml
|
61
|
+
- config/locales/fr.yml
|
45
62
|
- lib/neat-pages.rb
|
46
63
|
- lib/neat_pages/base.rb
|
64
|
+
- lib/neat_pages/engine.rb
|
47
65
|
- lib/neat_pages/errors.rb
|
66
|
+
- lib/neat_pages/helpers/builder.rb
|
67
|
+
- lib/neat_pages/helpers/navigation.rb
|
68
|
+
- lib/neat_pages/helpers/status.rb
|
48
69
|
- lib/neat_pages/helpers.rb
|
49
70
|
- lib/neat_pages/implants/action_controller_implant.rb
|
50
71
|
- lib/neat_pages/implants/mongoid_implant.rb
|
@@ -52,8 +73,8 @@ files:
|
|
52
73
|
- lib/neat_pages/implants.rb
|
53
74
|
- spec/neat-pages_spec.rb
|
54
75
|
- spec/neat_pages/base_spec.rb
|
55
|
-
- spec/neat_pages/helpers_spec.rb
|
56
76
|
- spec/spec_helper.rb
|
77
|
+
- vendor/assets/javascripts/jquery.hashchange.min.js
|
57
78
|
- LICENSE
|
58
79
|
- README.md
|
59
80
|
- Rakefile
|
@@ -66,21 +87,22 @@ rdoc_options: []
|
|
66
87
|
require_paths:
|
67
88
|
- lib
|
68
89
|
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
-
none: false
|
70
90
|
requirements:
|
71
91
|
- - ! '>='
|
72
92
|
- !ruby/object:Gem::Version
|
73
93
|
version: '0'
|
74
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
94
|
none: false
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
96
|
requirements:
|
77
97
|
- - ! '>='
|
78
98
|
- !ruby/object:Gem::Version
|
79
99
|
version: '0'
|
100
|
+
none: false
|
80
101
|
requirements: []
|
81
102
|
rubyforge_project: neat-pages
|
82
|
-
rubygems_version: 1.8.
|
103
|
+
rubygems_version: 1.8.10
|
83
104
|
signing_key:
|
84
105
|
specification_version: 3
|
85
106
|
summary: ''
|
86
107
|
test_files: []
|
108
|
+
has_rdoc:
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe NeatPages::Helpers do
|
4
|
-
describe "#status" do
|
5
|
-
context "with a 100 items pagination starting at 0 and having 10 items per page" do
|
6
|
-
let(:neat_pages) { NeatPages::Base.new(0, :per_page => 10, :total_items => 100) }
|
7
|
-
|
8
|
-
before { neat_pages.activate_helpers }
|
9
|
-
|
10
|
-
specify { neat_pages.helpers.status.should eql "1 to 10/100" }
|
11
|
-
end
|
12
|
-
|
13
|
-
context "with a 23 items pagination starting at page 3 and having 10 items per page" do
|
14
|
-
let(:neat_pages) { NeatPages::Base.new(3, :per_page => 10, :total_items => 23) }
|
15
|
-
|
16
|
-
before { neat_pages.activate_helpers }
|
17
|
-
|
18
|
-
specify { neat_pages.helpers.status.should eql "21 to 23/23" }
|
19
|
-
end
|
20
|
-
|
21
|
-
context "with a 0 items pagination starting at 0 and having 10 items per page" do
|
22
|
-
let(:neat_pages) { NeatPages::Base.new(0, :per_page => 10, :total_items => 0) }
|
23
|
-
|
24
|
-
before { neat_pages.activate_helpers }
|
25
|
-
|
26
|
-
specify { neat_pages.helpers.status.should be_empty }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|