alphabetical_paginate_uk 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6d5788477e3ec4838f47c0b7788650b193851955
4
- data.tar.gz: d95d3dcf8427f509e4d451ce2e2b2678d9054b2b
3
+ metadata.gz: 4db868fdca4359e328dea8fad7a6218303c03d86
4
+ data.tar.gz: 64a40e3785b8e1f78a08b1f0471cf2073e4bc1f8
5
5
  SHA512:
6
- metadata.gz: 1ad8cd2e1314d0bfcee339cf1e2a5c2bbd979c97becfca2f9043537b699eb2cbb4f882c29ba53df30de0793f734f94a0557f159c822932d217390b808f447d4d
7
- data.tar.gz: 6b27c55bc02b2b782267f88cba7bc5952628d6832ff24542a3c2cce2f51fcb0a624ad62598d7edca317100f1e00022f3c8483f318191f713b3833fc1b8abc215
6
+ metadata.gz: 3660eba7b61822344e4ea2c144cccc2720e38869baf900a9ca27189ea106f30ad43fdf41ce461916bccccf83799a92c67d04a0a3ad26f8cf209b8840d5693a34
7
+ data.tar.gz: f9e61cfb50fd0f327c9372ae2e8680680dab4500503fb9b1d107deac0464945777b95afec77c6c3cdc84b3e4bb9e82ca4689aff74305626190161023397ecb35
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.swp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in alphabetical_paginate.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 lingz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,174 @@
1
+ # AlphabeticalPaginate
2
+
3
+ A lightweight and highly customizable pagination gem for Ruby on Rails that generates alphabetic pagination categories from Collections or Arrays. It allows you to select the field you want to paginate on.
4
+
5
+ By default, it works with [Bootstrap Pagination](http://twitter.github.io/bootstrap/components.html#pagination) CSS and it is also fully compatible with the [will_paginate](https://github.com/mislav/will_paginate) in case you want to use both.
6
+
7
+ AlphabeticalPaginate incorporates efficient javascript partial page rerendering techniques and loading animations but also is non-obtrusive and falls back to standard href links.
8
+
9
+ It has two modes - if you're working with MySQL, it allows for low level database regex queries. Otherwise, it uses a buffered search to build an array. You should be able to easily modify the gem to work with other SQL databases (please make a pull-request if you do!).
10
+
11
+ We also now have Russian language support and Bootstrap 3 support.
12
+
13
+ Some code was inspired by [will_paginate](https://github.com/mislav/will_paginate).
14
+
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+ ```
20
+ gem 'alphabetical_paginate'
21
+ ```
22
+
23
+ And then execute:
24
+ ```bash
25
+ $ bundle install
26
+ ```
27
+
28
+ In case you're using the Rails 3.x assets pipeline remember to add it to your `production.rb` script:
29
+
30
+ ```rb
31
+ config.assets.precompile += %w( alphabetical_paginate.js )
32
+ ```
33
+
34
+ ## Basic Setup
35
+
36
+ Basic Pagination is as simple as adding a few lines to the controller and the view.
37
+
38
+ ### Controller
39
+ You simply need to call alpha_paginate on the desired Active Record Collection (i.e. `User.alpha_paginate`) or on any array (`User.all.alpha_paginate`). This method takes two parameters, the first always being `params[:letter]` and the second being an optional options hash.
40
+
41
+ Also, it takes a block in which you can specify the field you wish to paginate by (it can even be in another table). It returns the paginated subset of the collection, sorted by the pagination field. The method returns two values (the paginated array subsection, and an options hash), both of which must be stored as class variables.
42
+
43
+ It has a :db_mode parameter which tells the gem to perform low level SQL queries, which are both faster, and take up less memory. This is only supported for MySQL databases at this point.
44
+
45
+ *An example of its use is as such:*
46
+ #### If you are using MySQL / MySQL2
47
+ ```ruby
48
+ #app/controllers/users_controllers.rb
49
+ class UsersController < ApplicationController
50
+
51
+ def index
52
+ @users, @alphaParams = User.alpha_paginate(params[:letter], {db_mode: true, db_field: "name"})
53
+ end
54
+
55
+ ...
56
+ end
57
+ ```
58
+
59
+ #### If you are not using MySQL
60
+ ```ruby
61
+ #app/controllers/users_controllers.rb
62
+ class UsersController < ApplicationController
63
+
64
+ def index
65
+ @users, @alphaParams = User.all.alpha_paginate(params[:letter]){|user| user.name}
66
+ end
67
+
68
+ ...
69
+ end
70
+ ```
71
+
72
+ ### View
73
+ You need to call `alphabetical_paginate` that we just generated in the controller (i.e `<%= alphabetical_paginate @alphaParams %>`) in the view, whereever you would like to render the pagination selector div. You also **must wrap the content you want paginated in a div with id="pagination_table"**.
74
+
75
+ You can place as many `<%= alphabetical_paginate @alphaParams %>` as you wish on the page, if you want to render multiple pagination divs.
76
+
77
+ *An example is as such:*
78
+ ```html
79
+ #app/controllers/users/index.html.erb
80
+
81
+ <%= alphabetical_paginate @alphaParams %>
82
+
83
+ <div id="pagination_table">
84
+ <% User.all.each do |user| %>
85
+ ...
86
+ <% end %>
87
+ </div>
88
+ ```
89
+
90
+ ## Customization
91
+
92
+ ### Options
93
+ The gem is highly customizable. The `alpha_paginate ` method takes a hash as an optional second parameter like such:
94
+
95
+ ```ruby
96
+ #app/controllers/users_controllers.rb
97
+ class UsersController < ApplicationController
98
+
99
+ def index
100
+ @users, @alphaParams = User.all.alpha_paginate(params[:letter], {:enumerate => false}){|user| user.name}
101
+ end
102
+
103
+ ...
104
+ end
105
+ ```
106
+
107
+ The available options are as follows:
108
+
109
+ Key | Value | Default |Description
110
+ --- | --- | --- | ---
111
+ `:db_mode` | `Boolean` | `false` | Whether to activate low level SQL that are faster and more memory efficient
112
+ `:db_field` | `String` | `id` | Required if `db_mode` is `true`. The field to paginate / sort by (on the same collection).
113
+ `:enumerate` | `Boolean` | `false` | Whether you want the number field collapsed (all numbers go into `0`) or separate (`0`, `1`, `2`...).
114
+ `:default_field` | `String` | `"a"` | Which field you want the page to default to on first load (`"0"`, `"a"`. `"*"`).
115
+ `:paginate_all` | `Boolean` | `false` | Whether you want empty fields to still render in pagination. If it's falsy and `db_mode` is thruty is will perform one more aggregation query: set it to true if performances matter.
116
+ `:include_all` | `Boolean` | `true` | Whether you want `all` selector to be included in the pagination.
117
+ `:numbers` | `Boolean` | `true` | Whether you want numbers to be included in the pagination at all, either collapsed, or expanded (depending on `:enumerate`).
118
+ `:others` | `Boolean` | `true` | Whether you want all other characters (non alphanumeric) to be included in the pagination at all.
119
+ `:pagination_class` | `String` | `"pagination-centered"` | All the classes you would like to add to the rendered pagination selector div (for CSS purposes).
120
+ `:js` | `Boolean` | `"true"` | If you want the javascript with page-rerendering to be enabled.
121
+ `:support_language` | `Symbol` | `:en` | If you want russian letters support set this value to `:ru` (only if `I18n.locale` in your application set to `:ru`).
122
+ `:bootstrap3` | `Boolean` | `false` | If you want to enable bootstrap 3 support
123
+
124
+ ## Advanced Pagination
125
+
126
+ You can select a complex field to paginate by. Be careful, as this may be slow in large data sets. This only works if db_mode is disabled.
127
+
128
+ For instance, the following example paginates posts by the author's group's name (jumping across two tables).
129
+ It still returns the Post objects despite whatever field you use to paginate / sort it by (It still auto-sorts by the pagination field).
130
+ ```ruby
131
+ #app/controllers/users_controllers.rb
132
+ class UsersController < ApplicationController
133
+
134
+ def index
135
+ @posts, @alphaParams = Post.all.alpha_paginate(params[:letter]) do |post|
136
+ author = post.author
137
+ group = author.group
138
+ end
139
+ end
140
+
141
+ ...
142
+ end
143
+ ```
144
+
145
+ Also you can paginate by any array generally, it doesn't have to be a collection.
146
+ ```ruby
147
+ @friends, @params = friends.alpha_paginate(params[:letter]){|x| x}
148
+ ```
149
+
150
+ ## Rails 3.0 and Lower
151
+
152
+ The gem makes use of the Asset Pipeline, introduced in Rails 3.1. It still works with lower versions of Rails, however, you need to copy the assets over manually.
153
+
154
+ Copy the contents of `vendor/assets/javascripts` of this repo into the `public/javascripts` of your app
155
+ and also copy the contents of `vendor/assets/images` of this repo into the `public/images` of your app.
156
+
157
+ Also, there is one line in vendor/assets/javascripts that needs to be changed for Rails 3.0 support. That is, renaming the image path:
158
+ ```javascript
159
+ var img = "<img src='/assets/aloader.gif' class='loading'/>";
160
+ // RAILS 3.0 USERS -> Please delete the above line and uncomment the bottom line
161
+ //var img = "<img src='/images/aloader.gif' class='loading'/>";
162
+ ```
163
+
164
+ # Support
165
+
166
+ Please feel free to reach out and contact if you find the gem useful at all! Also, feel free to report / fix any bugs or add features.
167
+
168
+ ## To run tests
169
+
170
+ rspec
171
+
172
+ ## To publish the gem
173
+
174
+ rake release
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,61 @@
1
+ # coding: utf-8
2
+ class Array
3
+ def alpha_paginate current_field, params = {enumerate:false, default_field: "a",
4
+ paginate_all: false, numbers: true, include_all: true,
5
+ others: true, pagination_class: "pagination-centered",
6
+ js: true, support_language: :uk, bootstrap3: false,
7
+ slugged_link: false, slug_field: "slug", all_as_link: true}
8
+ params[:paginate_all] ||= false
9
+ params[:support_language] ||= :uk
10
+ params[:language] = AlphabeticalPaginate::Language.new(params[:support_language])
11
+ params[:include_all] = true if !params.has_key? :include_all
12
+ params[:numbers] = true if !params.has_key? :numbers
13
+ params[:others] = true if !params.has_key? :others
14
+ params[:js] = true if !params.has_key? :js
15
+ params[:default_field] ||= params[:include_all] ? "all" : params[:language].default_letter
16
+ params[:pagination_class] ||= "pagination-centered"
17
+ params[:slugged_link] ||= false
18
+ params[:slugged_link] = params[:slugged_link] && defined?(Babosa)
19
+ params[:slug_field] ||= "slug"
20
+ params[:all_as_link] = true if !params.has_key? :all_as_link
21
+
22
+ output = []
23
+ availableLetters = {}
24
+
25
+ current_field ||= params[:default_field]
26
+ current_field = current_field.mb_chars.downcase.to_s
27
+ all = params[:include_all] && current_field == "all"
28
+
29
+ self.each do |x|
30
+ slug = eval("x.#{params[:slug_field]}") if params[:slugged_link]
31
+
32
+ field_val = block_given? ? yield(x).to_s : x.id.to_s
33
+ field_letter = field_val[0].mb_chars.downcase.to_s
34
+
35
+ case field_letter
36
+ when params[:language].letters_regexp
37
+ availableLetters[field_letter] = true if !availableLetters.has_key? field_letter
38
+ regexp = params[:slugged_link] ? params[:language].slugged_regexp : params[:language].letters_regexp
39
+ field = params[:slugged_link] ? slug : field_letter
40
+ output << x if all || (current_field =~ regexp && current_field == field)
41
+ when /[0-9]/
42
+ if params[:enumerate]
43
+ availableLetters[field_letter] = true if !availableLetters.has_key? field_letter
44
+ output << x if all || (current_field =~ /[0-9]/ && field_letter == current_field)
45
+ else
46
+ availableLetters['0-9'] = true if !availableLetters.has_key? 'numbers'
47
+ output << x if all || current_field == "0-9"
48
+ end
49
+ else
50
+ availableLetters['*'] = true if !availableLetters.has_key? 'other'
51
+ output << x if all || current_field == "*"
52
+ end
53
+ end
54
+
55
+ params[:availableLetters] = availableLetters.collect{ |k,v| k.mb_chars.capitalize.to_s }
56
+ params[:currentField] = current_field.mb_chars.capitalize.to_s
57
+ output.sort! {|x, y| block_given? ? (yield(x).to_s <=> yield(y).to_s) : (x.id.to_s <=> y.id.to_s) }
58
+ return output, params
59
+ end
60
+ end
61
+
@@ -0,0 +1,145 @@
1
+ module AlphabeticalPaginate
2
+ module ControllerHelpers
3
+ def self.included(base)
4
+ base.extend(self)
5
+ end
6
+
7
+ def alpha_paginate current_field, params = {enumerate:false, default_field: "a",
8
+ paginate_all: false, numbers: true,
9
+ others: true, pagination_class: "pagination-centered",
10
+ batch_size: 500, db_mode: false,
11
+ db_field: "id", include_all: true,
12
+ js: true, support_language: :uk,
13
+ bootstrap3: false, slugged_link: false,
14
+ slug_field: "slug", all_as_link: true}
15
+ params[:paginate_all] ||= false
16
+ params[:support_language] ||= :uk
17
+ params[:language] = AlphabeticalPaginate::Language.new(params[:support_language])
18
+ params[:include_all] = true if !params.has_key? :include_all
19
+ params[:numbers] = true if !params.has_key? :numbers
20
+ params[:others] = true if !params.has_key? :others
21
+ params[:js] = true if !params.has_key? :js
22
+ params[:pagination_class] ||= "pagination-centered"
23
+ params[:batch_size] ||= 500
24
+ params[:db_mode] ||= false
25
+ params[:db_field] ||= "id"
26
+ params[:slugged_link] ||= false
27
+ params[:slugged_link] = params[:slugged_link] && defined?(Babosa)
28
+ params[:slug_field] ||= "slug"
29
+ params[:all_as_link] = true if !params.has_key? :all_as_link
30
+
31
+ output = []
32
+
33
+ if params[:db_mode]
34
+ letters = nil
35
+ if !params[:paginate_all]
36
+ letters = filter_by_cardinality( find_available_letters(params[:db_field]) )
37
+ set_default_field letters, params
38
+ end
39
+ params[:availableLetters] = letters.nil? ? [] : letters
40
+ end
41
+
42
+ if params[:include_all]
43
+ current_field ||= 'all'
44
+ all = current_field == "all"
45
+ end
46
+
47
+ current_field ||= params[:default_field]
48
+ current_field = current_field.mb_chars.downcase.to_s
49
+ all = params[:include_all] && current_field == "all"
50
+
51
+ if params[:db_mode]
52
+ if !ActiveRecord::Base.connection.adapter_name.downcase.include? "mysql"
53
+ raise "You need a mysql database to use db_mode with alphabetical_paginate"
54
+ end
55
+
56
+ if all
57
+ output = self
58
+ else
59
+
60
+ # In this case we can speed up the search taking advantage of the indices
61
+ can_go_quicker = (current_field =~ params[:language].letters_regexp) || (current_field =~ /[0-9]/ && params[:enumerate])
62
+
63
+
64
+ # Use LIKE the most as you can to take advantage of indeces on the field when available
65
+ # REGEXP runs always a full scan of the table!
66
+ # For more information about LIKE and indeces have a look at
67
+ # http://myitforum.com/cs2/blogs/jnelson/archive/2007/11/16/108354.aspx
68
+
69
+ # Also use some sanitization from ActiveRecord for the current field passed
70
+ if can_go_quicker
71
+ output = self.where("LOWER(%s) LIKE ?" % params[:db_field], current_field+'%')
72
+ else
73
+ regexp_to_check = current_field =~ /[0-9]/ ? '^[0-9]' : '^[^a-z0-9]'
74
+ output = self.where("LOWER(%s) REGEXP '%s.*'" % [params[:db_field], regexp_to_check])
75
+ end
76
+ end
77
+ else
78
+ availableLetters = {}
79
+ self.find_each({batch_size: params[:batch_size]}) do |x|
80
+ slug = eval("x.#{params[:slug_field]}") if params[:slugged_link]
81
+
82
+ field_val = block_given? ? yield(x).to_s : x.id.to_s
83
+ field_letter = field_val[0].mb_chars.downcase.to_s
84
+
85
+ case field_letter
86
+ when params[:language].letters_regexp
87
+ availableLetters[field_letter] = true if !availableLetters.has_key? field_letter
88
+ regexp = params[:slugged_link] ? params[:language].slugged_regexp : params[:language].letters_regexp
89
+ field = params[:slugged_link] ? slug : field_letter
90
+ output << x if all || (current_field =~ regexp && current_field == field)
91
+ when /[0-9]/
92
+ if params[:enumerate]
93
+ availableLetters[field_letter] = true if !availableLetters.has_key? field_letter
94
+ output << x if all || (current_field =~ /[0-9]/ && field_letter == current_field)
95
+ else
96
+ availableLetters['0-9'] = true if !availableLetters.has_key? 'numbers'
97
+ output << x if all || current_field == "0-9"
98
+ end
99
+ else
100
+ availableLetters['*'] = true if !availableLetters.has_key? 'other'
101
+ output << x if all || current_field == "*"
102
+ end
103
+ end
104
+ params[:availableLetters] = availableLetters.collect{ |k,v| k.mb_chars.capitalize.to_s }
105
+ output.sort! {|x, y| block_given? ? (yield(x).to_s <=> yield(y).to_s) : (x.id.to_s <=> y.id.to_s) }
106
+ end
107
+ params[:currentField] = current_field.mb_chars.capitalize.to_s
108
+ return ((params[:db_mode] && params[:db_field]) ? output.order("#{params[:db_field]} ASC") : output), params
109
+ end
110
+
111
+ private
112
+
113
+ def set_default_field(letters, params)
114
+ if letters.any?
115
+ params[:default_field] = letters.first
116
+ elsif params[:include_all]
117
+ params[:default_field] = 'all'
118
+ else
119
+ params[:default_field] = params[:language].default_letter
120
+ end
121
+ end
122
+
123
+ def filter_by_cardinality(letters)
124
+ letters.collect do |letter, count|
125
+ if count > 0
126
+ letter = letter.mb_chars.capitalize.to_s
127
+ (letter =~ /[а-і]/).nil? ? '*' : letter
128
+ else
129
+ nil
130
+ end
131
+ # repass again to filter duplicates *
132
+ end.uniq
133
+ end
134
+
135
+ def find_available_letters(db_field)
136
+ # safe the field (look for the ActiveRecord valid attributes)
137
+ # but allow explict table name prefixes in order to avoid 'field list is ambiguous' errors
138
+ if db_field.nil? || !self.attribute_names.include?(db_field.to_s.split('.').last)
139
+ db_field = 'id'
140
+ end
141
+ criteria = "substr( %s, 1 , 1)" % db_field
142
+ self.select(criteria).group(criteria).order(criteria).count(db_field)
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,6 @@
1
+ require 'rails'
2
+
3
+ module AlphabeticalPaginate
4
+ class Engine < ::Rails::Engine
5
+ end
6
+ end
@@ -0,0 +1,66 @@
1
+ # coding: utf-8
2
+ module AlphabeticalPaginate
3
+ class Language
4
+ APPROXIMATIONS = {
5
+ "Є" => "je",
6
+ "Ю" => "yu",
7
+ }
8
+
9
+ attr_reader :code
10
+
11
+ def initialize(code)
12
+ @code = code
13
+ end
14
+
15
+ def russian?
16
+ defined?(I18n) && I18n.locale == :uk && code == :uk
17
+ end
18
+
19
+ def letters_regexp
20
+ russian? ? /[а-іА-іa-zA-Z]/ : /[a-zA-Z]/
21
+ end
22
+
23
+ def slugged_regexp
24
+ /^(#{slugged_letters.values.join("|")})$/
25
+ end
26
+
27
+ def default_letter
28
+ russian? ? "а" : "a" # First 'a' is russian, second - english
29
+ end
30
+
31
+ # used in view_helper
32
+ def letters_range
33
+ if russian?
34
+ ["А","Б","В","Г","Д","Е","Є","Ж","З","И","І","Й","К","Л","М","Н","О","П","Р","С","Т","У","Ф","Х","Ц","Ч","Ш","Щ","Ю","Я"]
35
+ else
36
+ ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
37
+ end
38
+ end
39
+
40
+ def slugged_letters
41
+ hash = { "All" => "all" }
42
+ letters_range.each{ |x| hash[x] = normalize(x) }
43
+ hash
44
+ end
45
+
46
+ # used in view_helper
47
+ def output_letter(l)
48
+ (l == "All") ? all_field : l
49
+ end
50
+
51
+ # used in view_helper
52
+ def all_field
53
+ russian? ? 'Усі' : "All"
54
+ end
55
+
56
+ private
57
+
58
+ def normalize(letter)
59
+ if russian?
60
+ APPROXIMATIONS[letter] || letter.to_s.to_slug.normalize(transliterations: :ukrainian).to_s
61
+ else
62
+ letter.to_s.to_slug.normalize.to_s
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,13 @@
1
+ require 'alphabetical_paginate/view_helpers'
2
+ require 'alphabetical_paginate/controller_helper'
3
+ module AlphabeticalPaginate
4
+ class Railtie < Rails::Railtie
5
+ initializer "alphabetical_paginate.view_helpers" do
6
+ ActionView::Base.send :include, ViewHelpers
7
+ end
8
+ initializer "alphabetical_paginate.controller_helpers" do
9
+ ActiveRecord::Relation.send :include, ControllerHelpers
10
+ ActiveRecord::Base.send :include, ControllerHelpers
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module AlphabeticalPaginate
2
+ VERSION = "2.3.2"
3
+ end
@@ -0,0 +1,84 @@
1
+ # coding: utf-8
2
+ module AlphabeticalPaginate
3
+ module ViewHelpers
4
+ def alphabetical_paginate(options = {})
5
+ output = ""
6
+ links = ""
7
+ output += javascript_include_tag 'alphabetical_paginate' if options[:js] == true
8
+ options[:scope] ||= main_app
9
+
10
+ if options[:paginate_all]
11
+ range = options[:language].letters_range
12
+ if options[:others]
13
+ range += ["*"]
14
+ end
15
+ if options[:enumerate] && options[:numbers]
16
+ range = (0..9).to_a.map{|x| x.to_s} + range
17
+ elsif options[:numbers]
18
+ range = ["0-9"] + range
19
+ end
20
+ range.unshift "All" if (options[:include_all] && !range.include?("All"))
21
+ range.each do |l|
22
+ link_letter = l
23
+ if options[:slugged_link] && (l =~ options[:language].letters_regexp || l == "All")
24
+ link_letter = options[:language].slugged_letters[l]
25
+ end
26
+ letter_options = { letter: link_letter }
27
+ if !options[:all_as_link] && (l == "All")
28
+ letter_options[:letter] = nil
29
+ end
30
+
31
+ url = options[:scope].url_for(letter_options)
32
+ value = options[:language].output_letter(l)
33
+ if l == options[:currentField]
34
+ links += content_tag(:li, link_to(value, "#", "data-letter" => l), :class => "active")
35
+ elsif options[:db_mode] or options[:availableLetters].include? l
36
+ links += content_tag(:li, link_to(value, url, "data-letter" => l))
37
+ else
38
+ links += content_tag(:li, link_to(value, url, "data-letter" => l), :class => "disabled")
39
+ end
40
+ end
41
+ else
42
+ options[:availableLetters].sort!
43
+ options[:availableLetters] = options[:availableLetters][1..-1] + ["*"] if options[:availableLetters][0] == "*"
44
+ #Ensure that "All" is always at the front of the array
45
+ if options[:include_all]
46
+ options[:availableLetters].delete("All") if options[:availableLetters].include?("All")
47
+ options[:availableLetters].unshift("All")
48
+ end
49
+ options[:availableLetters] -= (1..9).to_a.map{|x| x.to_s} if !options[:numbers]
50
+ options[:availableLetters] -= ["*"] if !options[:others]
51
+
52
+ options[:availableLetters].each do |l|
53
+ link_letter = l
54
+ if options[:slugged_link] && (l =~ options[:language].letters_regexp || l == "All")
55
+ link_letter = options[:language].slugged_letters[l]
56
+ end
57
+ letter_options = { letter: link_letter }
58
+ if !options[:all_as_link] && (l == "All")
59
+ letter_options[:letter] = nil
60
+ end
61
+
62
+ url = options[:scope].url_for(letter_options)
63
+ value = options[:language].output_letter(l)
64
+ links += content_tag(:li, link_to(value, url, "data-letter" => l), :class => ("active" if l == options[:currentField] ))
65
+ end
66
+ end
67
+
68
+ element = options[:bootstrap3] ? 'ul' : 'div'
69
+ if options[:pagination_class] != "none"
70
+ pagination = "<#{element} class='pagination %s alpha'>" % options[:pagination_class]
71
+ else
72
+ pagination = "<#{element} class='pagination alpha'>"
73
+ end
74
+ pagination +=
75
+ (options[:bootstrap3] ? "" : "<ul>") +
76
+ links +
77
+ (options[:bootstrap3] ? "" : "</ul>") +
78
+ (options[:bootstrap3] ? "" : "</div>")
79
+
80
+ output += pagination
81
+ output.html_safe
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,8 @@
1
+ require "alphabetical_paginate/version"
2
+ require "alphabetical_paginate/array"
3
+ require "alphabetical_paginate/language"
4
+ require "alphabetical_paginate/railtie" if defined?(Rails)
5
+
6
+ module AlphabeticalPaginate
7
+ require 'alphabetical_paginate/engine'
8
+ end
@@ -0,0 +1,15 @@
1
+ module AlphabeticalPaginate
2
+ class AlphaExample
3
+ attr_accessor :id, :word
4
+
5
+ def initialize(letter)
6
+ @id = letter
7
+ @word = letter.reverse
8
+ end
9
+
10
+ def to_s
11
+ "{%s, %s}" % [@id, @word]
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,244 @@
1
+ # coding: utf-8
2
+ require 'alpha_example'
3
+ require 'alphabetical_paginate'
4
+ require_relative '#{File.dirname(__FILE__)}/../../lib/alphabetical_paginate/view_helpers'
5
+
6
+ # stub methods
7
+ def javascript_include_tag x
8
+ return ""
9
+ end
10
+ class String
11
+ def html_safe
12
+ return self
13
+ end
14
+ end
15
+
16
+ class RouterMock
17
+ def url_for(options)
18
+ options[:letter] ? '?letter='+options[:letter] : '/'
19
+ end
20
+ end
21
+
22
+ def main_app
23
+ RouterMock.new()
24
+ end
25
+
26
+ def link_to(value, url, options)
27
+ "<a href='#{url}' data-letter=\"#{options["data-letter"]}\">#{value}</a>"
28
+ end
29
+
30
+ def content_tag(type, el, html_options={})
31
+ "<#{type.to_s} class='#{html_options[:class] || ''}'>#{el}</#{type.to_s}>"
32
+ end
33
+
34
+
35
+ module AlphabeticalPaginate
36
+
37
+ describe AlphabeticalPaginate do
38
+
39
+ describe "#alpha_paginate" do
40
+ before :each do
41
+ @list = ["aa", "ab", "ac",
42
+ "ba", "bb", "bg",
43
+ "ca", "cd", "ce"].map do |x|
44
+ AlphaExample.new(x)
45
+ end
46
+ end
47
+
48
+ it "should paginate by id automatically" do
49
+ expectedCollection = ["ba", "bb", "bg"].map do |x|
50
+ AlphaExample.new(x)
51
+ end
52
+ expectedParams = {
53
+ availableLetters: ["a", "b", "c"],
54
+ currentField: "b",
55
+ enumerate: false,
56
+ }
57
+ collection, params = @list.alpha_paginate("b")
58
+ collection.to_s.should ==
59
+ expectedCollection.to_s
60
+ params.to_s.should include
61
+ expectedParams.to_s
62
+ end
63
+
64
+ it "should paginate by block when needed" do
65
+ expectedCollection = ["ab", "bb"].map do |x|
66
+ AlphaExample.new(x)
67
+ end
68
+ expectedParams = {
69
+ availableLetters: ["a", "b", "c", "g", "d", "e"],
70
+ currentField: "b",
71
+ enumerate: false,
72
+ }
73
+ collection, params = @list.alpha_paginate("b") do |x|
74
+ x.word
75
+ end
76
+ collection.to_s.should ==
77
+ expectedCollection.to_s
78
+ params.to_s.should include
79
+ expectedParams.to_s
80
+ end
81
+ end
82
+
83
+ describe "#alpha_paginate in russian characters" do
84
+ before :each do
85
+ I18n.locale = :ru
86
+ @list = ["аа", "аб", "ас",
87
+ "ба", "бб", "бв",
88
+ "са", "сд", "се"].map do |x|
89
+ AlphaExample.new(x)
90
+ end
91
+ end
92
+
93
+ it "should paginate by id automatically" do
94
+ expectedCollection = ["са", "сд", "се"].map do |x|
95
+ AlphaExample.new(x)
96
+ end
97
+ expectedParams = {
98
+ availableLetters: ["а", "б", "с"],
99
+ currentField: "с",
100
+ enumerate: false,
101
+ }
102
+ collection, params = @list.alpha_paginate("с", { support_language: :ru })
103
+ collection.to_s.should ==
104
+ expectedCollection.to_s
105
+ params.to_s.should include
106
+ expectedParams.to_s
107
+ end
108
+
109
+ it "should paginate for russian characters with default 'a' character" do
110
+ expectedCollection = ["аа", "аб", "ас"].map do |x|
111
+ AlphaExample.new(x)
112
+ end
113
+ expectedParams = {
114
+ availableLetters: ["а", "б", "с"],
115
+ currentField: "а",
116
+ enumerate: false,
117
+ }
118
+ collection, params = @list.alpha_paginate(nil, { include_all: false, support_language: :ru })
119
+ collection.to_s.should ==
120
+ expectedCollection.to_s
121
+ params.to_s.should include
122
+ expectedParams.to_s
123
+ end
124
+ end
125
+
126
+ include ViewHelpers
127
+
128
+ describe "#alphabetical_paginate" do
129
+ before :each do
130
+ @list = []
131
+ (["@!#"] + (0..9).to_a.map{|x| x.to_s} + ("A".."Z").to_a).each do |x|
132
+ ("A".."Y").to_a.each do |y|
133
+ @list << x + y
134
+ end
135
+ end
136
+ @list.map! do |x|
137
+ AlphaExample.new(x)
138
+ end
139
+ end
140
+
141
+ it "should have div tags and pagination classes" do
142
+ index, params = @list.alpha_paginate(nil)
143
+ pagination = alphabetical_paginate(params)
144
+ pagination.should include "div", "pagination"
145
+ end
146
+
147
+ it "should include a numbers and others field" do
148
+ index, params = @list.alpha_paginate(nil)
149
+ pagination = alphabetical_paginate(params)
150
+ (["*"] + ["0-9"] + ("A".."Z").to_a.map{|x|
151
+ 'data-letter="%s"'%x}).each do |x|
152
+ pagination.should include x
153
+ end
154
+ end
155
+
156
+ it "should default all values when necessary" do
157
+ index, params = @list.alpha_paginate(nil, {})
158
+ pagination = alphabetical_paginate(params)
159
+ (["*"] + ["0-9"] + ("A".."Z").to_a.map{|x|
160
+ 'data-letter="%s"'%x}).each do |x|
161
+ pagination.should include x
162
+ end
163
+ end
164
+
165
+ it "should hide values that don't exist" do
166
+ index, params = @list.alpha_paginate(nil){|x| x.word}
167
+ pagination = alphabetical_paginate(params)
168
+ (("A".."Y").to_a.map{|x|
169
+ 'data-letter="%s"'%x}).each do |x|
170
+ pagination.should include x
171
+ end
172
+ pagination.should_not include 'data-letter="Z"', 'data-letter="*"',
173
+ 'data-letter="0-9"'
174
+ end
175
+
176
+ it "should enumerate when asked" do
177
+ index, params = @list.alpha_paginate(nil, {enumerate: true})
178
+ pagination = alphabetical_paginate(params)
179
+ (("0".."9").to_a.map{|x|
180
+ 'data-letter="%s"'% x.to_s }).each do |x|
181
+ pagination.should include x
182
+ end
183
+
184
+ end
185
+
186
+ it "should display all when asked" do
187
+ index, params = @list.alpha_paginate(nil, {paginate_all: true,
188
+ enumerate: true}){|x| x.word}
189
+ pagination = alphabetical_paginate(params)
190
+ (["*"] + (0..9).to_a.map{|x| x.to_s} + ("A".."Z").to_a.map{|x|
191
+ 'data-letter="%s"'%x}).each do |x|
192
+ pagination.should include x
193
+ end
194
+ end
195
+
196
+ it "should include 'all' and '0-9' fields" do
197
+ index, params = @list.alpha_paginate(nil, { include_all: true })
198
+ pagination = alphabetical_paginate(params)
199
+ (["All", "0-9"].map{|x|
200
+ 'data-letter="%s"'%x}).each do |x|
201
+ pagination.should include x
202
+ end
203
+ end
204
+
205
+ it "should include All as link" do
206
+ index, params = @list.alpha_paginate("A", { include_all: true })
207
+ pagination = alphabetical_paginate(params)
208
+ pagination.should include "href='?letter=All'"
209
+ end
210
+
211
+ it "should not include All as link" do
212
+ index, params = @list.alpha_paginate("A", { include_all: true, all_as_link: false })
213
+ pagination = alphabetical_paginate(params)
214
+ pagination.should_not include "href='?letter=All'"
215
+ end
216
+ end
217
+
218
+ describe "#alphabetical_paginate in russian characters" do
219
+ before :each do
220
+ @list = []
221
+ ("А".."Я").to_a.each do |x|
222
+ ("А".."Т").to_a.each do |y|
223
+ @list << x + y
224
+ end
225
+ end
226
+ @list.map! do |x|
227
+ AlphaExample.new(x)
228
+ end
229
+ @russian_array = []
230
+ "АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЭЮЯ".each_char{ |x| @russian_array << x }
231
+ end
232
+
233
+ it "should display russian characters through additional attribute(language)" do
234
+ I18n.locale = :ru
235
+ index, params = @list.alpha_paginate(nil, { paginate_all: true, others: false, support_language: :ru }){|x| x.word}
236
+ pagination = alphabetical_paginate(params)
237
+ (["0"] + @russian_array.map{|x|
238
+ 'data-letter="%s"'%x}).each do |x|
239
+ pagination.should include x
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,68 @@
1
+ # coding: utf-8
2
+ require 'alphabetical_paginate'
3
+
4
+ module AlphabeticalPaginate
5
+ describe Language do
6
+
7
+ context "English language" do
8
+ before(:all) do
9
+ I18n.locale = :en
10
+ @language = AlphabeticalPaginate::Language.new(I18n.locale)
11
+ end
12
+
13
+ it "should return false on russian? method" do
14
+ @language.russian?.should be_false
15
+ end
16
+
17
+ it "should return /[a-zA-Z]/ regexp" do
18
+ @language.letters_regexp.should eq(/[a-zA-Z]/)
19
+ end
20
+
21
+ it "should return array of english letters" do
22
+ @language.letters_range.should eq(("A".."Z").to_a)
23
+ end
24
+
25
+ it "should return english representation of 'All' field and other english letters (for view helper)" do
26
+ (["All"] + ("A".."Z").to_a).map do |l|
27
+ @language.output_letter(l).should eq(l)
28
+ end
29
+ end
30
+
31
+ it "should return english representation of 'a' letter" do
32
+ @language.default_letter.should eq("a")
33
+ end
34
+ end
35
+
36
+ context "Russian language" do
37
+ before(:all) do
38
+ I18n.locale = :ru
39
+ @language = AlphabeticalPaginate::Language.new(I18n.locale)
40
+ @russian_string = "АБВГДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЮЯ"
41
+ @russian_array = []
42
+ @russian_string.each_char{ |x| @russian_array << x }
43
+ end
44
+
45
+ it "should return true on russian? method" do
46
+ @language.russian?.should be_true
47
+ end
48
+
49
+ it "should return /[а-яА-Я]/ regexp" do
50
+ @language.letters_regexp.should eq(/[а-яА-Я]/)
51
+ end
52
+
53
+ it "should return array of russian letters" do
54
+ @language.letters_range.should eq(@russian_array)
55
+ end
56
+
57
+ it "should return russian representation of 'All' field and other russian letters (for view helper)" do
58
+ (["Все"] + @russian_array).map do |l|
59
+ @language.output_letter(l).should eq(l)
60
+ end
61
+ end
62
+
63
+ it "should return russian representation of 'а' letter" do
64
+ @language.default_letter.should eq("а")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,18 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ config.include Rails.application.routes.url_helpers
12
+
13
+ # Run specs in random order to surface order dependencies. If you find an
14
+ # order dependency and want to debug it, you can fix the order by providing
15
+ # the seed, which is printed after each run.
16
+ # --seed 1234
17
+ config.order = 'random'
18
+ end
@@ -0,0 +1,4 @@
1
+ module Helpers
2
+ include ActionView::Base::ViewHelpers
3
+ include ActionView::Helpers::AssetTagHelper
4
+ end
Binary file
@@ -0,0 +1,64 @@
1
+ $(function() {
2
+ // deal with old browsers
3
+ var hasHistory = !!(window.history && window.history.pushState);
4
+
5
+ var img = "<img src='/assets/aloader.gif' class='loading'/>";
6
+ // RAILS 3.0 USERS -> Please delete the above line and uncomment the bottom line
7
+ // ensure that the image directory matches
8
+ // var img = "<img src='/img/aloader.gif' class='loading'/>";
9
+
10
+ var navbar = $(".pagination.alpha a");
11
+ // Pick the handler list: just a quick check for the jQuery version (see here: http://bugs.jquery.com/ticket/10589)
12
+ var handlers = navbar.data ? navbar.data('events') : jQuery._data(navbar[0], 'events');
13
+
14
+ if (!handlers || -1 !== $.inArray(onNavbarClick, handlers.click)) {
15
+ $(document).on("click", ".pagination.alpha a", onNavbarClick);
16
+ if(hasHistory){
17
+ // bind the popstate
18
+ bindPopState(location.href);
19
+ }
20
+ }
21
+
22
+ function onNavbarClick(e) {
23
+ e.preventDefault();
24
+ var url = location.href,
25
+ letter = $(this).data("letter");
26
+ if (/letter/.test(url)) {
27
+ url = url.replace(/letter=[^&]*/, "letter=" + letter);
28
+ } else {
29
+ if (/\?/.test(url)) {
30
+ url += "&letter=" + letter;
31
+ } else {
32
+ url += "?letter=" + letter;
33
+ }
34
+ }
35
+ loadPage(url);
36
+ // deal with browser support
37
+ if(hasHistory){
38
+ history.pushState(null, document.title, url);
39
+ }
40
+ }
41
+
42
+ // let navigate the browser throught the ajax history
43
+ function bindPopState(initialUrl){
44
+ $(window).bind("popstate", function() {
45
+ var newUrl = location.href;
46
+ var diff = newUrl.replace(initialUrl, '');
47
+ // skip initial popstate
48
+ // skip anchor links (used for JS links)
49
+ if (diff !== '' && diff !== '#') {
50
+ loadPage(newUrl);
51
+ }
52
+ });
53
+ }
54
+
55
+ function loadPage(url){
56
+ $(".pagination").html(img);
57
+ $.get(url, function (result) {
58
+ $(".pagination").html($(".pagination", result).html());
59
+ $("#pagination_table").html($("#pagination_table", result).html());
60
+ });
61
+ }
62
+
63
+
64
+ });
@@ -0,0 +1 @@
1
+ //= require ./alphabetical_paginate
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alphabetical_paginate_uk
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
- - refleckt
7
+ - lingz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
@@ -66,13 +66,35 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: Alphabetical Pagination for UK
69
+ description: Alphabetical Pagination UK
70
70
  email:
71
- - m.antevora@gmail.com
71
+ - lz781@nyu.edu
72
72
  executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
- files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lib/alphabetical_paginate.rb
83
+ - lib/alphabetical_paginate/array.rb
84
+ - lib/alphabetical_paginate/controller_helper.rb
85
+ - lib/alphabetical_paginate/engine.rb
86
+ - lib/alphabetical_paginate/language.rb
87
+ - lib/alphabetical_paginate/railtie.rb
88
+ - lib/alphabetical_paginate/version.rb
89
+ - lib/alphabetical_paginate/view_helpers.rb
90
+ - spec/alpha_example.rb
91
+ - spec/alphabetical_paginate_spec.rb
92
+ - spec/language_spec.rb
93
+ - spec/spec_helper.rb
94
+ - spec/support/helpers.rb
95
+ - vendor/assets/images/aloader.gif
96
+ - vendor/assets/javascripts/alphabetical_paginate.js
97
+ - vendor/assets/javascripts/index.js
76
98
  homepage: https://github.com/refleckt/alphabetical_paginate_uk
77
99
  licenses:
78
100
  - MIT
@@ -97,4 +119,9 @@ rubygems_version: 2.5.2
97
119
  signing_key:
98
120
  specification_version: 4
99
121
  summary: Pagination
100
- test_files: []
122
+ test_files:
123
+ - spec/alpha_example.rb
124
+ - spec/alphabetical_paginate_spec.rb
125
+ - spec/language_spec.rb
126
+ - spec/spec_helper.rb
127
+ - spec/support/helpers.rb