smart_listing 0.9.1 → 0.9.2
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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +4 -0
- data/app/assets/javascripts/smart_listing/smart_listing.coffee +247 -247
- data/app/helpers/smart_listing/application_helper.rb +3 -3
- data/app/helpers/smart_listing/helper.rb +257 -257
- data/lib/smart_listing.rb +117 -112
- data/lib/smart_listing/version.rb +1 -1
- metadata +3 -3
@@ -1,259 +1,259 @@
|
|
1
1
|
module SmartListing
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
2
|
+
module Helper
|
3
|
+
module ControllerExtensions
|
4
|
+
def smart_listing_create name, collection, options = {}
|
5
|
+
name = name.to_sym
|
6
|
+
|
7
|
+
list = SmartListing::Base.new(name, collection, options)
|
8
|
+
list.setup(params, cookies)
|
9
|
+
|
10
|
+
@smart_listings ||= {}
|
11
|
+
@smart_listings[name] = list
|
12
|
+
|
13
|
+
list.collection
|
14
|
+
end
|
15
|
+
|
16
|
+
def smart_listing name
|
17
|
+
@smart_listings[name.to_sym]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Builder
|
22
|
+
# Params that should not be visible in pagination links (pages, per-page, sorting, etc.)
|
23
|
+
UNSAFE_PARAMS = {:authenticity_token => nil, :utf8 => nil}
|
24
|
+
|
25
|
+
class_attribute :smart_listing_helpers
|
26
|
+
|
27
|
+
def initialize(smart_listing_name, smart_listing, template, options, proc)
|
28
|
+
@smart_listing_name, @smart_listing, @template, @options, @proc = smart_listing_name, smart_listing, template, options, proc
|
29
|
+
end
|
30
|
+
|
31
|
+
def paginate options = {}
|
32
|
+
if @smart_listing.collection.respond_to? :current_page
|
33
|
+
@template.paginate @smart_listing.collection, :remote => true, :param_name => @smart_listing.param_names[:page], :params => UNSAFE_PARAMS
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def collection
|
38
|
+
@smart_listing.collection
|
39
|
+
end
|
40
|
+
|
41
|
+
def pagination_per_page_links options = {}
|
42
|
+
@template.content_tag(:div, :class => "pagination_per_page #{'disabled' if empty?}") do
|
43
|
+
if @smart_listing.count > @smart_listing.page_sizes.first
|
44
|
+
@template.concat(@template.t('views.pagination.per_page'))
|
45
|
+
per_page_sizes = @smart_listing.page_sizes.clone
|
46
|
+
per_page_sizes.push(0) if @smart_listing.unlimited_per_page?
|
47
|
+
per_page_sizes.each do |p|
|
48
|
+
name = p == 0 ? @template.t('views.pagination.unlimited') : p
|
49
|
+
if @smart_listing.per_page.to_i != p
|
50
|
+
@template.concat(@template.link_to(name, @template.url_for(sanitize_params(@template.params.merge(@smart_listing.param_names[:per_page] => p, @smart_listing.param_names[:page] => 1))), :remote => true))
|
51
|
+
else
|
52
|
+
@template.concat(@template.content_tag(:span, name))
|
53
|
+
end
|
54
|
+
break if p > @smart_listing.count
|
55
|
+
end
|
56
|
+
@template.concat ' | '
|
57
|
+
end if @smart_listing.options[:paginate]
|
58
|
+
@template.concat(@template.t('views.pagination.total'))
|
59
|
+
@template.concat(@template.content_tag(:span, @smart_listing.count, :class => "count"))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def sortable title, attribute, options = {}
|
64
|
+
extra = options.delete(:extra)
|
65
|
+
|
66
|
+
sort_params = {
|
67
|
+
@smart_listing.param_names[:sort_attr] => attribute,
|
68
|
+
@smart_listing.param_names[:sort_order] => (@smart_listing.sort_order == "asc") ? "desc" : "asc",
|
69
|
+
@smart_listing.param_names[:sort_extra] => extra
|
70
|
+
}
|
71
|
+
|
72
|
+
@template.link_to(@template.url_for(sanitize_params(@template.params.merge(sort_params))), :class => "sortable", :data => {:attr => attribute}, :remote => true) do
|
73
|
+
@template.concat(title)
|
74
|
+
if @smart_listing.sort_attr == attribute && (!@smart_listing.sort_extra || @smart_listing.sort_extra == extra.to_s)
|
75
|
+
@template.concat(@template.content_tag(:span, "", :class => (@smart_listing.sort_order == "asc" ? "glyphicon glyphicon-chevron-up" : "glyphicon glyphicon-chevron-down")))
|
76
|
+
else
|
77
|
+
@template.concat(@template.content_tag(:span, "", :class => "glyphicon glyphicon-resize-vertical"))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def update options = {}
|
83
|
+
part = options.delete(:partial) || @smart_listing.partial || @smart_listing_name
|
84
|
+
|
85
|
+
@template.render(:partial => 'smart_listing/update_list', :locals => {:name => @smart_listing_name, :part => part, :smart_listing => self})
|
86
|
+
end
|
87
|
+
|
88
|
+
# Renders the main partial (whole list)
|
89
|
+
def render_list
|
90
|
+
if @smart_listing.partial
|
91
|
+
@template.render :partial => @smart_listing.partial, :locals => {:smart_listing => self}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Basic render block wrapper that adds smart_listing reference to local variables
|
96
|
+
def render options = {}, locals = {}, &block
|
97
|
+
if locals.empty?
|
98
|
+
options[:locals] ||= {}
|
99
|
+
options[:locals].merge!(:smart_listing => self)
|
100
|
+
else
|
101
|
+
locals.merge!({:smart_listing => self})
|
102
|
+
end
|
103
|
+
@template.render options, locals, &block
|
104
|
+
end
|
105
|
+
|
106
|
+
# Add new item button & placeholder to list
|
107
|
+
def item_new options = {}
|
108
|
+
@template.concat(@template.content_tag(:tr, '', :class => "info new_item_placeholder disabled"))
|
109
|
+
@template.concat(@template.content_tag(:tr, :class => "info new_item_action #{'disabled' if !empty? && max_count?}") do
|
110
|
+
@template.concat(@template.content_tag(:td, :colspan => options.delete(:colspan)) do
|
111
|
+
@template.concat(@template.content_tag(:p, :class => "no_records pull-left #{'disabled' unless empty?}") do
|
112
|
+
@template.concat(options.delete(:no_items_text))
|
113
|
+
end)
|
114
|
+
@template.concat(@template.link_to(options.delete(:link), :remote => true, :class => "btn pull-right #{'disabled' if max_count?}") do
|
115
|
+
@template.concat(@template.content_tag(:i, '', :class => "glyphicon glyphicon-plus"))
|
116
|
+
@template.concat(" ")
|
117
|
+
@template.concat(options.delete(:text))
|
118
|
+
end)
|
119
|
+
end)
|
120
|
+
end)
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
|
124
|
+
# Check if smart list is empty
|
125
|
+
def empty?
|
126
|
+
@smart_listing.count == 0
|
127
|
+
end
|
128
|
+
|
129
|
+
# Check if smart list reached its item max count
|
130
|
+
def max_count?
|
131
|
+
return false if @smart_listing.max_count.nil?
|
132
|
+
@smart_listing.count >= @smart_listing.max_count
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def sanitize_params params
|
138
|
+
params.merge(UNSAFE_PARAMS)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Outputs smart list container
|
143
|
+
def smart_listing_for name, *args, &block
|
144
|
+
raise ArgumentError, "Missing block" unless block_given?
|
145
|
+
name = name.to_sym
|
146
|
+
options = args.extract_options!
|
147
|
+
bare = options.delete(:bare)
|
148
|
+
|
149
|
+
builder = Builder.new(name, @smart_listings[name], self, options, block)
|
150
|
+
|
151
|
+
output =""
|
152
|
+
|
153
|
+
data = {}
|
154
|
+
data['max-count'] = @smart_listings[name].max_count if @smart_listings[name].max_count && @smart_listings[name].max_count > 0
|
155
|
+
data['href'] = @smart_listings[name].href if @smart_listings[name].href
|
156
|
+
|
157
|
+
if bare
|
158
|
+
output = capture(builder, &block)
|
159
|
+
else
|
160
|
+
output = content_tag(:div, :class => "smart_listing", :id => name, :data => data) do
|
161
|
+
concat(content_tag(:div, "", :class => "loading"))
|
162
|
+
concat(content_tag(:div, :class => "content") do
|
163
|
+
concat(capture(builder, &block))
|
164
|
+
end)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
output
|
169
|
+
end
|
170
|
+
|
171
|
+
# Render item action buttons (ie. edit, destroy and custom ones)
|
172
|
+
def smart_listing_item_actions actions = []
|
173
|
+
content_tag(:span) do
|
174
|
+
actions.each do |action|
|
175
|
+
next unless action.is_a?(Hash)
|
176
|
+
|
177
|
+
if action.has_key?(:if)
|
178
|
+
unless action[:if]
|
179
|
+
concat(content_tag(:i, '', :class => "glyphicon glyphicon-remove-circle"))
|
180
|
+
next
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
case action.delete(:name).to_sym
|
185
|
+
when :edit
|
186
|
+
url = action.delete(:url)
|
187
|
+
html_options = {
|
188
|
+
:remote => true,
|
189
|
+
:class => "edit",
|
190
|
+
:title => t("smart_listing.actions.edit")
|
191
|
+
}.merge(action)
|
192
|
+
|
193
|
+
concat(link_to(url, html_options) do
|
194
|
+
concat(content_tag(:i, '', :class => "glyphicon glyphicon-pencil"))
|
195
|
+
end)
|
196
|
+
when :destroy
|
197
|
+
url = action.delete(:url)
|
198
|
+
icon = action.delete(:icon) || "glyphicon glyphicon-trash"
|
199
|
+
html_options = {
|
200
|
+
:remote => true,
|
201
|
+
:class => "destroy",
|
202
|
+
:method => :delete,
|
203
|
+
:title => t("smart_listing.actions.destroy"),
|
204
|
+
:data => {:confirmation => action.delete(:confirmation) || t("smart_listing.msgs.destroy_confirmation")},
|
205
|
+
}.merge(action)
|
206
|
+
|
207
|
+
concat(link_to(url, html_options) do
|
208
|
+
concat(content_tag(:i, '', :class => icon))
|
209
|
+
end)
|
210
|
+
when :custom
|
211
|
+
url = action.delete(:url)
|
212
|
+
icon = action.delete(:icon)
|
213
|
+
html_options = action
|
214
|
+
|
215
|
+
concat(link_to(url, html_options) do
|
216
|
+
concat(content_tag(:i, '', :class => icon))
|
217
|
+
end)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def smart_listing_limit_left name
|
224
|
+
name = name.to_sym
|
225
|
+
smart_listing = @smart_listings[name]
|
226
|
+
|
227
|
+
smart_listing.max_count - smart_listing.count
|
228
|
+
end
|
229
|
+
|
230
|
+
#################################################################################################
|
231
|
+
# JS helpers:
|
232
|
+
|
233
|
+
# Updates the smart list
|
234
|
+
def smart_listing_update name
|
235
|
+
name = name.to_sym
|
236
|
+
smart_listing = @smart_listings[name]
|
237
|
+
builder = Builder.new(name, smart_listing, self, {}, nil)
|
238
|
+
render(:partial => 'smart_listing/update_list', :locals => {
|
239
|
+
:name => smart_listing.name,
|
240
|
+
:part => smart_listing.partial,
|
241
|
+
:smart_listing => builder,
|
242
|
+
:smart_listing_data => {
|
243
|
+
:params => smart_listing.all_params,
|
244
|
+
'max-count' => smart_listing.max_count,
|
245
|
+
}
|
246
|
+
})
|
247
|
+
end
|
248
|
+
|
249
|
+
# Renders single item (i.e for create, update actions)
|
250
|
+
def smart_listing_item name, item_action, object = nil, partial = nil, options = {}
|
251
|
+
name = name.to_sym
|
252
|
+
type = object.class.name.downcase.to_sym if object
|
253
|
+
id = object.id if object
|
254
|
+
object_key = options.delete(:object_key) || :object
|
255
|
+
|
256
|
+
render(:partial => "smart_listing/item/#{item_action.to_s}", :locals => {:name => name, :id => id, :object_key => object_key, :object => object, :part => partial})
|
257
|
+
end
|
258
|
+
end
|
259
259
|
end
|