neat-pages 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://secure.travis-ci.org/demarque/neat-pages.png?branch=master)](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
|