flex_infinite_scroll 0.1.3 → 0.3.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.
- checksums.yaml +5 -5
- data/lib/flex_infinite_scroll.rb +4 -21
- data/lib/flex_infinite_scroll/actionview.rb +6 -0
- data/lib/flex_infinite_scroll/actionview/extension.rb +39 -0
- data/lib/flex_infinite_scroll/activerecord.rb +6 -0
- data/lib/flex_infinite_scroll/activerecord/extension.rb +19 -0
- data/lib/flex_infinite_scroll/activerecord/helpers.rb +38 -0
- data/vendor/assets/javascript/flex_infinite_scroll.js +303 -101
- metadata +10 -21
- data/lib/flex_infinite_scroll/view_helpers.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 566821164973e19e83ef507c84b5b77f0d66e148
|
4
|
+
data.tar.gz: e22f3d0148db3746989eef48649e82376c12f02d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8a8bf1db18cdb92f26ef9953c5fee972f64c43de1e05f1fe0afae24fe21bbd07e425032d5675a8db5921c4bdab062ae80f2d6914bb542da046e9645be0a0c49
|
7
|
+
data.tar.gz: 4b6567f7892c2bc453d32a45a3a1866c8dd2eade75192f8386c3c7502262febd9e5295e6cad57c59a94f872619887eaaa734839ecd5241b5741c975e2b9fb61b
|
data/lib/flex_infinite_scroll.rb
CHANGED
@@ -1,25 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Infinite scroll module
|
4
|
-
require 'flex_infinite_scroll/view_helpers'
|
5
|
-
require 'sanitize'
|
6
|
-
|
7
3
|
module FlexInfiniteScroll
|
8
|
-
class Engine < ::Rails::Engine
|
9
|
-
ActionView::Base.send :include, FlexInfiniteScroll::ViewHelpers
|
10
|
-
end
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
def infinite_scroll(page = 1, page_size = (ENV['FIS_PAGE_SIZE'] || 20))
|
13
|
-
page ||= 1
|
14
|
-
page = page.to_i if page.class == String
|
15
|
-
offset_skip = (page - 1) * page_size
|
16
|
-
total_page = (count('*') / page_size.to_f).ceil
|
17
|
-
{
|
18
|
-
data: offset(offset_skip).limit(page_size),
|
19
|
-
total_page: total_page,
|
20
|
-
prev_page: (page == 1 ? nil : page - 1),
|
21
|
-
current_page: page,
|
22
|
-
next_page: (page == total_page ? nil : page + 1)
|
23
|
-
}
|
24
|
-
end
|
4
|
+
class Engine < ::Rails::Engine; end
|
25
5
|
end
|
6
|
+
|
7
|
+
require 'flex_infinite_scroll/activerecord'
|
8
|
+
require 'flex_infinite_scroll/actionview'
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexInfiniteScroll
|
4
|
+
module ActionViewExtension
|
5
|
+
def fis_tag(data = nil, fis_config = {}, container_config = {})
|
6
|
+
container_config[:data] ||= {}
|
7
|
+
container_config[:class] = "fis-container #{container_config[:class]}"
|
8
|
+
|
9
|
+
virtual_el_size = fis_config[:virtualScrollElementSize]
|
10
|
+
|
11
|
+
page = fis_config[:startPage] || 1
|
12
|
+
fis_config[:startPage] = page + 1
|
13
|
+
|
14
|
+
fis_config.each do |k, _v|
|
15
|
+
container_config[:data][k.to_s.underscore] = fis_config[k]
|
16
|
+
end
|
17
|
+
|
18
|
+
content_tag :div, container_config do
|
19
|
+
data = data.fis(page: page, per_page: fis_config[:perPage])
|
20
|
+
data_html = data.map { |el| yield el }.join
|
21
|
+
|
22
|
+
baloons = []
|
23
|
+
if virtual_el_size
|
24
|
+
(fis_config[:startPage]..data.total_pages).each do |page_number|
|
25
|
+
baloons.push(
|
26
|
+
content_tag(:div, nil,
|
27
|
+
class: 'fis-baloon',
|
28
|
+
data: {
|
29
|
+
baloon_page: page_number
|
30
|
+
},
|
31
|
+
style: "height: #{virtual_el_size * data.per_page}px")
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
(data_html + baloons.join).html_safe
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexInfiniteScroll
|
4
|
+
module ActiveRecordExtension
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
require 'flex_infinite_scroll/activerecord/helpers'
|
8
|
+
|
9
|
+
included do
|
10
|
+
def self.fis(config = { page: 1 })
|
11
|
+
page = config[:page].to_i
|
12
|
+
per_page = config[:per_page] ? config[:per_page].to_i : 20
|
13
|
+
offset(per_page * (page - 1)).limit(per_page).extending do
|
14
|
+
include FlexInfiniteScroll::ActiveRecordHelpers
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexInfiniteScroll
|
4
|
+
module ActiveRecordHelpers
|
5
|
+
def render_json
|
6
|
+
prepare_render.merge(data: as_json)
|
7
|
+
end
|
8
|
+
|
9
|
+
def render_html
|
10
|
+
prepare_render.merge(data: map { |el| yield el }.join.html_safe)
|
11
|
+
end
|
12
|
+
|
13
|
+
def per_page
|
14
|
+
values[:limit]
|
15
|
+
end
|
16
|
+
|
17
|
+
def page
|
18
|
+
(values[:offset] / per_page) + 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def next_page
|
22
|
+
page == total_pages ? nil : page + 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def total_pages
|
26
|
+
(except(:offset, :limit, :order).count / per_page).ceil
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def prepare_render
|
32
|
+
{
|
33
|
+
next_page: next_page,
|
34
|
+
total_pages: total_pages
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,108 +1,310 @@
|
|
1
1
|
// Flex Infinite Scroll initialization
|
2
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
|
-
|
3
|
+
/*
|
4
|
+
config = {
|
5
|
+
customResponse: function(target, data) {
|
6
|
+
'Data processing after loading next page. By default data will be added as HTML.'
|
7
|
+
},
|
8
|
+
eventTarget: 'Select different DOM element for scroll event',
|
9
|
+
requestUrl: 'URL for next page.',
|
10
|
+
loadMargin: 'Bottom margin in pixels, when will start loading next page. Default: 150',
|
11
|
+
startPage: 'Start page for loading data. Default: 1',
|
12
|
+
requestType: 'Type of AJAX request. Default: GET',
|
13
|
+
customParams: function(params) {
|
14
|
+
Parameters that will be sent with next page request. Default: {page: next_page}
|
15
|
+
return params
|
16
|
+
},
|
17
|
+
windowScroll: Attach scroll event to window object,
|
18
|
+
customResponseAttributes: {
|
19
|
+
next_page: 'next_page',
|
20
|
+
data: 'data'
|
21
|
+
},
|
22
|
+
virtualScroll: 'Enable virtual scroll',
|
23
|
+
virtualScrollElementSize: 'Element size for virtual scroll',
|
24
|
+
perfectScrollbarSupport: 'Enable perfect-scrollbar support'
|
25
|
+
perfectScrollbarConfig: 'Config for perfect-scrollbar'
|
26
|
+
}
|
27
|
+
*/
|
28
|
+
|
29
|
+
'use strict';
|
30
|
+
|
31
|
+
class flexIS {
|
32
|
+
constructor(targetObject, config = {}) {
|
33
|
+
this.targetObject = (typeof(targetObject) === 'object' ? targetObject : document.querySelector(targetObject));
|
34
|
+
this.config = {...config, ...this.targetObject.dataset};
|
35
|
+
this.loading = false;
|
36
|
+
this.nextPage = this.config.startPage || 1;
|
37
|
+
this.totalElements;
|
38
|
+
|
39
|
+
this.config.requestType = this.config.requestType || 'GET';
|
40
|
+
this.config.loadMargin = this.config.loadMargin || 150;
|
41
|
+
this.config.eventTarget = prepareEventTarget(this);
|
42
|
+
this.#customResponseAttributesSet();
|
43
|
+
|
44
|
+
function prepareEventTarget(object) {
|
45
|
+
var eventTarget = document.querySelector(object.config.eventTarget) || object.targetObject;
|
46
|
+
if (["true", true].includes(object.config.windowScroll)) {
|
47
|
+
return window;
|
48
|
+
} else {
|
49
|
+
return eventTarget;
|
50
|
+
}
|
42
51
|
}
|
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
|
-
|
52
|
+
|
53
|
+
if (["true", true].includes(this.config.perfectScrollbarSupport)) {
|
54
|
+
let PSConfig = this.config.perfectScrollbarConfig || {}
|
55
|
+
PSConfig.minScrollbarLength = PSConfig.minScrollbarLength || 40
|
56
|
+
this.perfectScrollbar = new PerfectScrollbar(
|
57
|
+
this.targetObject,
|
58
|
+
PSConfig
|
59
|
+
);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
// Init infinite scroll
|
64
|
+
init() {
|
65
|
+
if(this.#virtualScroll().enabled()) {
|
66
|
+
this.#virtualScroll().pagesLoad();
|
67
|
+
} else {
|
68
|
+
this.#getData();
|
69
|
+
}
|
70
|
+
|
71
|
+
this.config.eventTarget.addEventListener('scroll', () => {
|
72
|
+
if(this.#virtualScroll().enabled()) {
|
73
|
+
this.#virtualScroll().pagesLoad();
|
74
|
+
} else {
|
75
|
+
if (this.#scrollHitBottom() && this.nextPage) {
|
76
|
+
this.#getData();
|
77
|
+
};
|
78
|
+
}
|
79
|
+
this.#hideInvisibleContent();
|
80
|
+
});
|
81
|
+
return this;
|
82
|
+
}
|
83
|
+
|
84
|
+
// Reset scroll to specific page
|
85
|
+
resetScroll(page) {
|
86
|
+
this.targetObject.innerHTML = '';
|
87
|
+
this.nextPage = page || this.config.startPage || 1;
|
88
|
+
this.#getData();
|
89
|
+
return this;
|
90
|
+
}
|
91
|
+
|
92
|
+
// Append element to container
|
93
|
+
appendChild(el) {
|
94
|
+
this.#appendElementToContainer(el);
|
95
|
+
return this;
|
96
|
+
}
|
97
|
+
|
98
|
+
// Private methods
|
99
|
+
|
100
|
+
// Run data request for next page
|
101
|
+
#getData = (page = this.nextPage, forceLoad = false) => {
|
102
|
+
var xhr = new XMLHttpRequest();
|
103
|
+
var params;
|
104
|
+
const beforeLoadEvent = new CustomEvent('FlexIS:beforeLoad');
|
105
|
+
const afterLoadEvent = new CustomEvent('FlexIS:afterLoad');
|
106
|
+
|
107
|
+
if (!page || (this.loading && !forceLoad)) return false;
|
108
|
+
|
109
|
+
this.loading = true;
|
110
|
+
|
111
|
+
params = this.#customParams({page: parseInt(page, 10)});
|
112
|
+
|
113
|
+
this.targetObject.dispatchEvent(beforeLoadEvent);
|
114
|
+
xhr.open('GET', this.#requestUrl(params));
|
115
|
+
xhr.onload = () => {
|
116
|
+
var json = JSON.parse(xhr.response);
|
117
|
+
|
118
|
+
this.loading = false;
|
119
|
+
|
120
|
+
if (xhr.status === 200) {
|
121
|
+
this.#customResponse(json, page);
|
122
|
+
if (!this.#virtualScroll().enabled()) {
|
123
|
+
this.nextPage = json[this.config.customResponseAttributes.next_page];
|
124
|
+
if (this.#scrollHitBottom()) this.#getData();
|
71
125
|
}
|
72
126
|
}
|
73
|
-
|
74
|
-
|
75
|
-
|
127
|
+
|
128
|
+
this.targetObject.dispatchEvent(afterLoadEvent);
|
129
|
+
|
76
130
|
}
|
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
|
-
|
131
|
+
xhr.send();
|
132
|
+
}
|
133
|
+
|
134
|
+
// Full scroll height
|
135
|
+
#scrollHeight = () => {
|
136
|
+
return this.targetObject.scrollHeight;
|
137
|
+
}
|
138
|
+
|
139
|
+
// Top scroll position
|
140
|
+
#scrollTop = () => {
|
141
|
+
return this.config.eventTarget.scrollTop || this.config.eventTarget.scrollY || 0;
|
142
|
+
}
|
143
|
+
|
144
|
+
// Get container size
|
145
|
+
#containerSize = () => {
|
146
|
+
return this.config.eventTarget.innerHeight || this.targetObject.offsetHeight;
|
147
|
+
}
|
148
|
+
|
149
|
+
// Container position
|
150
|
+
#containerPosition = () => {
|
151
|
+
return this.#scrollTop() + this.#containerSize() + this.config.loadMargin;
|
152
|
+
}
|
153
|
+
|
154
|
+
// Add custom params to request
|
155
|
+
#customParams = (params) => {
|
156
|
+
var customParams = this.config.customParams;
|
157
|
+
if (customParams) {
|
158
|
+
if (typeof customParams === "function") {
|
159
|
+
return customParams(params);
|
160
|
+
} else if (typeof customParams === "object") {
|
161
|
+
return {...customParams, ...params};
|
162
|
+
} else if (typeof customParams === "string") {
|
163
|
+
return {...JSON.parse(customParams), ...params};
|
164
|
+
}
|
165
|
+
}
|
166
|
+
return params;
|
167
|
+
}
|
168
|
+
|
169
|
+
// Response handling
|
170
|
+
#customResponse = (json, page) => {
|
171
|
+
var customResponse = this.config.customResponse;
|
172
|
+
var data = json[this.config.customResponseAttributes.data];
|
173
|
+
var div;
|
174
|
+
|
175
|
+
delete json[this.config.customResponseAttributes.data];
|
176
|
+
|
177
|
+
if (data.constructor === Array) {
|
178
|
+
data.forEach((el) => {
|
179
|
+
var htmlEl
|
180
|
+
if (typeof customResponse === "function") {
|
181
|
+
htmlEl = customResponse(el, json);
|
182
|
+
} else {
|
183
|
+
let div = document.createElement('div');
|
184
|
+
div.innerHTML = el;
|
185
|
+
htmlEl = div.children[0];
|
186
|
+
}
|
187
|
+
this.#appendElementToContainer(htmlEl, page);
|
188
|
+
})
|
189
|
+
} else if (data.constructor === String) {
|
190
|
+
div = document.createElement('div');
|
191
|
+
div.innerHTML = data;
|
192
|
+
while (div.children.length > 0) {
|
193
|
+
this.#appendElementToContainer(div.children[0], page);
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
this.#hideInvisibleContent();
|
198
|
+
|
199
|
+
if (this.#virtualScroll().enabled()) {
|
200
|
+
this.#virtualScroll().destroyBaloon(page);
|
201
|
+
}
|
202
|
+
|
203
|
+
if (this.perfectScrollbar) {
|
204
|
+
this.perfectScrollbar.update();
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
#appendElementToContainer = (el, page) => {
|
209
|
+
if (this.#virtualScroll().enabled()) {
|
210
|
+
this.#virtualScroll().insertBeforeBaloon(page, el);
|
211
|
+
} else {
|
212
|
+
this.targetObject.appendChild(el);
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
// Hide invisible content, when leaving active zone
|
217
|
+
#hideInvisibleContent = () => {
|
218
|
+
var elems = this.targetObject.children;
|
219
|
+
for (let i = 0; i < elems.length; i++) {
|
220
|
+
let elem = elems[i];
|
221
|
+
let elementTopPosition = elems[i].offsetTop + elems[i].offsetHeight - this.#scrollTop();
|
222
|
+
let elementBottomPosition = elems[i].offsetTop - elems[i].offsetHeight - this.#scrollTop() - this.#containerSize();
|
223
|
+
|
224
|
+
if (elem.className.includes('ps__rail-x', 'ps__rail-y')) continue;
|
225
|
+
|
226
|
+
if (elementTopPosition <= 0 || elementBottomPosition >= 0) {
|
227
|
+
if (elem.style.visibility === 'hidden') continue;
|
228
|
+
elem.style.visibility = 'hidden';
|
229
|
+
} else {
|
230
|
+
if (elem.style.visibility === '') continue;
|
231
|
+
elem.style.visibility = '';
|
232
|
+
}
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
#virtualScroll = () => {
|
237
|
+
return {
|
238
|
+
enabled: () => {
|
239
|
+
return ["true", true].includes(this.config.virtualScroll);
|
240
|
+
},
|
241
|
+
insertBeforeBaloon: (page, el) => {
|
242
|
+
var baloon = this.targetObject.querySelector(`[data-baloon-page="${page}"]`)
|
243
|
+
var newHeight;
|
244
|
+
this.targetObject.insertBefore(el, baloon);
|
245
|
+
newHeight = baloon.offsetHeight - el.offsetHeight;
|
246
|
+
baloon.style.height = newHeight + 'px';
|
247
|
+
|
248
|
+
},
|
249
|
+
pagesLoad: () => {
|
250
|
+
var baloons = [...this.targetObject.getElementsByClassName('fis-baloon')];
|
251
|
+
var containerPosition = this.#containerPosition();
|
252
|
+
baloons.forEach(baloon => {
|
253
|
+
var visibleBottom = this.#containerPosition() > baloon.offsetTop;
|
254
|
+
var visibleTop = this.#scrollTop() < baloon.offsetTop + baloon.offsetHeight;
|
255
|
+
if (baloon.dataset.loading) return;
|
256
|
+
if (visibleBottom && visibleTop) {
|
257
|
+
baloon.dataset.loading = true;
|
258
|
+
this.#getData(baloon.dataset.baloonPage, true);
|
259
|
+
}
|
260
|
+
})
|
261
|
+
},
|
262
|
+
destroyBaloon: (page) => {
|
263
|
+
this.targetObject.querySelector(`[data-baloon-page="${page}"]`).remove();
|
264
|
+
}
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
// Update response attributes
|
269
|
+
#customResponseAttributesSet = () => {
|
270
|
+
var attr = this.config.customResponseAttributes || {};
|
271
|
+
attr.next_page = attr.next_page || 'next_page';
|
272
|
+
attr.data = attr.data || 'data';
|
273
|
+
attr.elements_left = attr.elements_left || 'elements_left';
|
274
|
+
this.config.customResponseAttributes = attr
|
275
|
+
}
|
276
|
+
|
277
|
+
// Generate url with params
|
278
|
+
#requestUrl = (params) => {
|
279
|
+
var encodedString = [];
|
280
|
+
for (var prop in params) {
|
281
|
+
if (params.hasOwnProperty(prop)) {
|
282
|
+
encodedString.push(encodeURI(prop + '=' + params[prop]));
|
283
|
+
}
|
284
|
+
}
|
285
|
+
return this.config.requestUrl + '?' + encodedString.join('&');
|
286
|
+
}
|
287
|
+
|
288
|
+
// Check when load next page
|
289
|
+
#scrollHitBottom = () => {
|
290
|
+
return this.#scrollHeight() - this.#containerPosition() <= 0;
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
document.addEventListener('DOMContentLoaded', () => {
|
295
|
+
var fisObjects = [...document.getElementsByClassName('fis-container')];
|
296
|
+
fisObjects.forEach(object => {
|
297
|
+
object.data = {
|
298
|
+
flexIS: new flexIS(object).init()
|
299
|
+
};
|
300
|
+
})
|
301
|
+
})
|
302
|
+
|
303
|
+
document.addEventListener('turbolinks:load', () => {
|
304
|
+
var fisObjects = [...document.getElementsByClassName('fis-turbolinks-container')];
|
305
|
+
fisObjects.forEach(object => {
|
306
|
+
object.data = {
|
307
|
+
flexIS: new flexIS(object).init()
|
308
|
+
};
|
103
309
|
})
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
}
|
108
|
-
})
|
310
|
+
})
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flex_infinite_scroll
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Ignatov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: sanitize
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 4.6.3
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 4.6.3
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rails
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,7 +31,11 @@ extensions: []
|
|
45
31
|
extra_rdoc_files: []
|
46
32
|
files:
|
47
33
|
- lib/flex_infinite_scroll.rb
|
48
|
-
- lib/flex_infinite_scroll/
|
34
|
+
- lib/flex_infinite_scroll/actionview.rb
|
35
|
+
- lib/flex_infinite_scroll/actionview/extension.rb
|
36
|
+
- lib/flex_infinite_scroll/activerecord.rb
|
37
|
+
- lib/flex_infinite_scroll/activerecord/extension.rb
|
38
|
+
- lib/flex_infinite_scroll/activerecord/helpers.rb
|
49
39
|
- vendor/assets/javascript/flex_infinite_scroll.js
|
50
40
|
homepage: https://github.com/aignatov-bio/flex_infinite_scroll
|
51
41
|
licenses:
|
@@ -65,11 +55,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
55
|
- - ">="
|
66
56
|
- !ruby/object:Gem::Version
|
67
57
|
version: '0'
|
68
|
-
requirements:
|
69
|
-
- jQuery
|
58
|
+
requirements: []
|
70
59
|
rubyforge_project:
|
71
|
-
rubygems_version: 2.
|
60
|
+
rubygems_version: 2.6.14.3
|
72
61
|
signing_key:
|
73
62
|
specification_version: 4
|
74
|
-
summary:
|
63
|
+
summary: Infinite scroll for Ruby on Rails applications on pure JavaScript.
|
75
64
|
test_files: []
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module FlexInfiniteScroll
|
4
|
-
module ViewHelpers
|
5
|
-
include ActionView::Helpers::TagHelper
|
6
|
-
include ActionView::Context
|
7
|
-
|
8
|
-
def fis_init_list(data, partial, config = {})
|
9
|
-
result = if config[:targetContainer]
|
10
|
-
fis_get_list(data, partial, 'html')
|
11
|
-
else
|
12
|
-
content_tag :div, class: "fis-container #{config[:container_class] || ''}" do
|
13
|
-
fis_get_list(data, partial, 'html')
|
14
|
-
end
|
15
|
-
end
|
16
|
-
config[:scrollContainer] ||= (config[:targetContainer] || 'body')
|
17
|
-
config[:targetContainer] ||= '.fis-container'
|
18
|
-
result += javascript_tag do
|
19
|
-
"$('#{config[:scrollContainer]}').flexInfiniteScroll(#{config.to_json})".html_safe
|
20
|
-
end
|
21
|
-
Sanitize.fragment(result,
|
22
|
-
Sanitize::Config.merge(Sanitize::Config::RELAXED,
|
23
|
-
elements: Sanitize::Config::RELAXED[:elements] + %w(script))).html_safe
|
24
|
-
end
|
25
|
-
|
26
|
-
def fis_next_page(data, partial)
|
27
|
-
data[:data] = fis_get_list(data, partial, 'json')
|
28
|
-
data
|
29
|
-
end
|
30
|
-
|
31
|
-
def fis_get_list(data, partial, format)
|
32
|
-
result = ''
|
33
|
-
data[:data].each do |member|
|
34
|
-
result += if format == 'json'
|
35
|
-
render_to_string(partial: partial, locals: { fis_object: member })
|
36
|
-
else
|
37
|
-
render partial: partial, locals: { fis_object: member }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
Sanitize.fragment(result, Sanitize::Config::RELAXED).html_safe
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|