flex_infinite_scroll 0.1.4 → 0.2.0

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: 6dca995d94c2ad3e09019b7d273940ba9aaab2c7
4
- data.tar.gz: 11616db0db37cbefd5d5a303d528440baa5c11f5
3
+ metadata.gz: 0b2a488c4c9a4e8d1c412c49188eb0a5b386e6ab
4
+ data.tar.gz: b2e285288ffaba7bd0b3c0e82d1ee74a1f38bdac
5
5
  SHA512:
6
- metadata.gz: cd01ef3e67277c1805e030e6cce972978eb8e0f88839eb5fcf5166c7a7fb9497c1f1ecb5c504c979d45e3292cf5458d6315339cdd93855e65b3beeaeba7b402c
7
- data.tar.gz: 83e655f62ab35e6c8f2375bddfeca4996dafb9add85de27eb1ef24d557133e63cfd71069f26d197b767bbb6fd206576b517160ab12508fdd21f152e2c3ccf8c6
6
+ metadata.gz: 66f797500898467fb03d9602f69756962dee609f10673a8efd925dd36893c37e586fa3d0c7db8956ee25ad98793d79160662cf12728df563e7609fa3d36fa1c4
7
+ data.tar.gz: 4df833cc66d11917c625d88cc2caade11fcee8863d61b8a8f5639eefebf42331018760a3dfbe548ec07fe2f328e16e40dc87a4a14b246366bca16e472cb4b271
@@ -1,24 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Infinite scroll module
4
- require 'flex_infinite_scroll/view_helpers'
5
-
6
3
  module FlexInfiniteScroll
7
- class Engine < ::Rails::Engine
8
- ActionView::Base.send :include, FlexInfiniteScroll::ViewHelpers
9
- end
10
- extend ActiveSupport::Concern
11
- def infinite_scroll(page = 1, page_size = (ENV['FIS_PAGE_SIZE'] || 20))
12
- page ||= 1
13
- page = page.to_i if page.class == String
14
- offset_skip = (page - 1) * page_size
15
- total_page = (count('*') / page_size.to_f).ceil
16
- {
17
- data: offset(offset_skip).limit(page_size),
18
- total_page: total_page,
19
- prev_page: (page == 1 ? nil : page - 1),
20
- current_page: page,
21
- next_page: (page == total_page ? nil : page + 1)
22
- }
23
- end
4
+ class Engine < ::Rails::Engine; end
24
5
  end
@@ -1,122 +1,148 @@
1
1
  // Flex Infinite Scroll initialization
2
2
 
3
+ 'use strict';
3
4
 
4
- function flexInfiniteScroll(object_id,config = {}) {
5
- // Config preparing
6
- var startPage = config.startPage || 1;
7
- var nextPage = startPage + 1;
8
- var dataUrl = config.url;
9
- var scrollContainer = (object_id == 'body' ? document.body : document.getElementById(object_id));
10
- var queryParams = config.queryParams;
11
- var dataProcess = config.dataProcess;
12
- var initialLoad = config.initialLoad;
13
- var loadMargin = config.loadMargin || 150;
14
- var beforeAction = config.beforeAction;
15
- var afterAction = config.afterAction;
16
- var targetContainer= config.targetContainer || scrollContainer ;
17
- var eventTarget = (object_id == 'body' ? window : scrollContainer);
18
- if (config.lastPage) nextPage = 'last';
19
- scrollContainer.dataset.fisNextPage = nextPage;
20
- scrollContainer.dataset.fisUrl = dataUrl;
21
- scrollContainer.dataset.fisLoading = 0;
22
-
23
- function getScrollHeight(){
24
- if (object_id == 'body'){
25
- return document.documentElement.scrollHeight;
26
- } else {
27
- return eventTarget.scrollHeight;
28
- }
29
-
5
+ class flexIS {
6
+ constructor(targetObject, config = {}) {
7
+ this.targetObject = (typeof(targetObject) === 'object' ? targetObject : document.querySelector(targetObject));
8
+ this.config = {...config, ...this.targetObject.dataset};
9
+ this.loading = false;
10
+ this.nextPage = this.config.startPage || 1;
11
+
12
+ this.config.requestType = this.config.requestType || 'GET';
13
+ this.config.loadMargin = this.config.loadMargin || 150;
14
+ this.config.eventTarget = prepareEventTarget(this);
15
+
16
+ function prepareEventTarget(object) {
17
+ var eventTarget = document.querySelector(object.config.eventTarget) || object.targetObject;
18
+ if (object.config.windowScroll) {
19
+ return window
20
+ } else {
21
+ return eventTarget
22
+ }
23
+ }
24
+ }
25
+
26
+ init() {
27
+ this.#getData();
28
+ this.config.eventTarget.addEventListener('scroll', () => {
29
+ if (this.#scrollHitBottom() && this.nextPage) {
30
+ this.#getData();
31
+ };
32
+ });
33
+ return this;
30
34
  }
31
35
 
32
- function urlParams(object) {
33
- var encodedString = '';
34
- for (var prop in object) {
35
- if (object.hasOwnProperty(prop)) {
36
- if (encodedString.length > 0) {
37
- encodedString += '&';
38
- }
39
- encodedString += encodeURI(prop + '=' + object[prop]);
36
+ resetScroll(page) {
37
+ this.targetObject.innerHTML = '';
38
+ this.nextPage = page || this.config.startPage || 1;
39
+ this.#getData();
40
+ return this;
41
+ }
42
+
43
+ // Private methods
44
+
45
+ #getData = (page = this.nextPage ) => {
46
+ var xhr = new XMLHttpRequest();
47
+ var params;
48
+ const beforeLoadEvent = new CustomEvent('FlexIS:beforeLoad');
49
+ const afterLoadEvent = new CustomEvent('FlexIS:afterLoad');
50
+
51
+ if (!page || this.loading) return false;
52
+
53
+ this.loading = true;
54
+
55
+ params = this.#customParams({page: parseInt(page, 10)});
56
+
57
+ this.targetObject.dispatchEvent(beforeLoadEvent)
58
+ xhr.open('GET', this.#requestUrl(params));
59
+ xhr.onload = () => {
60
+ var json = JSON.parse(xhr.response);
61
+
62
+ this.loading = false;
63
+
64
+ if (xhr.status === 200) {
65
+ this.#customResponse(json)
66
+ this.nextPage = json.next_page;
67
+ if (this.#scrollHitBottom()) this.#getData();
40
68
  }
41
- }
42
- return encodedString;
69
+
70
+ this.targetObject.dispatchEvent(afterLoadEvent)
71
+
72
+ }
73
+ xhr.send();
74
+ }
75
+
76
+ #scrollHeight = () => {
77
+ return this.targetObject.scrollHeight;
78
+ }
79
+
80
+ #scrollTop = () => {
81
+ return this.config.eventTarget.scrollTop || this.config.eventTarget.scrollY;
43
82
  }
44
-
45
- function getData(page = 1){
46
- // Check for loading process and last page
47
- if (scrollContainer.dataset.fisLoading === '1' || page == 'last') return false;
48
- scrollContainer.dataset.fisLoading = 1;
49
- // before load action
50
- if (beforeAction) {
51
- if (typeof(beforeAction) == 'function') {
52
- beforeAction();
53
- }else if (typeof(beforeAction) == 'string') {
54
- eval(beforeAction);
83
+
84
+ #containerSize = () => {
85
+ return this.config.eventTarget.innerHeight || this.targetObject.offsetHeight;
86
+ }
87
+
88
+ #customParams = (params) => {
89
+ var customParams = this.config.customParams;
90
+ if (customParams) {
91
+ if (typeof customParams === "function") {
92
+ return customParams(params);
93
+ } else if (typeof customParams === "object") {
94
+ return {...customParams, ...params};
95
+ } else if (typeof customParams === "string") {
96
+ return {...JSON.parse(customParams), ...params};
97
+ }
55
98
  }
56
- }
57
- var xhr = new XMLHttpRequest();
58
- var params = (queryParams || {page: page});
59
- xhr.open('GET', scrollContainer.dataset.fisUrl + '?' + urlParams(params));
60
- xhr.onload = function() {
61
- var json = JSON.parse(xhr.response)
62
- if (xhr.status === 200) {
63
- if (dataProcess){
64
- // custom user processor
65
- dataProcess(json,targetContainer);
66
- } else {
67
- // default data processor
68
- var div = document.createElement('div');
99
+ return params;
100
+ }
101
+
102
+ #customResponse = (json) => {
103
+ var customResponse = this.config.customResponse;
104
+ var div;
105
+ if (typeof customResponse === "function") {
106
+ customResponse(this.targetObject, json);
107
+ } else {
108
+ div = document.createElement('div');
69
109
  div.innerHTML = json.data;
70
110
  while (div.children.length > 0) {
71
- document.getElementById(targetContainer).appendChild(div.children[0]);
111
+ this.targetObject.appendChild(div.children[0]);
72
112
  }
73
- }
74
- scrollContainer.dataset.fisNextPage = json.next_page || 'last';
75
- scrollContainer.dataset.fisLoading = 0;
76
- if (scrollNotApear()) {
77
- // check if on initial load not enough elements on screen
78
- getData(scrollContainer.dataset.fisNextPage);
79
- }
80
- // after load action
81
- if (afterAction) {
82
- if (typeof(afterAction) == 'function') {
83
- afterAction();
84
- }else if (typeof(afterAction) == 'string') {
85
- eval(afterAction)
86
- }
87
- }
88
- } else {
89
- scrollContainer.dataset.fisLoading = 0;
90
113
  }
91
- };
92
- xhr.send();
114
+
93
115
  }
94
-
95
- // intial load
96
- if (initialLoad) {
97
- getData(startPage);
98
- } else if (scrollNotApear()) {
99
- // check if on initial load not enough elements on screen
100
- getData(scrollContainer.dataset.fisNextPage);
116
+
117
+ #requestUrl = (params) => {
118
+ var encodedString = [];
119
+ for (var prop in params) {
120
+ if (params.hasOwnProperty(prop)) {
121
+ encodedString.push(encodeURI(prop + '=' + params[prop]));
122
+ }
123
+ }
124
+ return this.config.requestUrl + '?' + encodedString.join('&');
101
125
  }
102
-
103
- // check if body scroll
104
-
105
- function scrollNotApear(){
106
- var containerSize=(object_id == 'body' ? eventTarget.innerHeight : eventTarget.offsetHeight);
107
- var scrollSize=getScrollHeight();
108
- return (scrollSize - containerSize - loadMargin <= 0);
126
+
127
+ #scrollHitBottom = () => {
128
+ return (this.#scrollHeight() - this.#scrollTop() - this.#containerSize() - this.config.loadMargin <= 0);
109
129
  }
130
+ }
110
131
 
111
- eventTarget.addEventListener('scroll', function() {
112
- var scrollTop= (object_id == 'body' ? eventTarget.scrollY : eventTarget.scrollTop);
113
- var containerSize=(object_id == 'body' ? eventTarget.innerHeight : eventTarget.offsetHeight);
114
- var scrollSize=getScrollHeight();
115
- if (scrollTop + containerSize > scrollSize - loadMargin && scrollContainer.dataset.fisNextPage != 'last'){
116
- getData(scrollContainer.dataset.fisNextPage);
117
- };
132
+ document.addEventListener('DOMContentLoaded', () => {
133
+ var fisObjects = [...document.getElementsByClassName('fis-container')];
134
+ fisObjects.forEach(object => {
135
+ object.data = {
136
+ flexIS: new flexIS(object).init()
137
+ }
118
138
  })
119
-
120
-
121
-
122
- }
139
+ })
140
+
141
+ document.addEventListener('turbolinks:load', () => {
142
+ var fisObjects = [...document.getElementsByClassName('fis-turbolinks-container')];
143
+ fisObjects.forEach(object => {
144
+ object.data = {
145
+ flexIS: new flexIS(object).init()
146
+ }
147
+ })
148
+ })
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flex_infinite_scroll
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.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: 2019-05-05 00:00:00.000000000 Z
11
+ date: 2020-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -31,7 +31,6 @@ extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
33
  - lib/flex_infinite_scroll.rb
34
- - lib/flex_infinite_scroll/view_helpers.rb
35
34
  - vendor/assets/javascript/flex_infinite_scroll.js
36
35
  homepage: https://github.com/aignatov-bio/flex_infinite_scroll
37
36
  licenses:
@@ -56,6 +55,5 @@ rubyforge_project:
56
55
  rubygems_version: 2.6.14.3
57
56
  signing_key:
58
57
  specification_version: 4
59
- summary: Infinite scroll for Ruby on Rails applications on pure JavaScript. Also has
60
- Kaminari support for pagination.
58
+ summary: Infinite scroll for Ruby on Rails applications on pure JavaScript.
61
59
  test_files: []
@@ -1,52 +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
- data = kaminari_prepare(data) if config[:kaminari]
10
- result = if config[:targetContainer]
11
- fis_get_list(data, partial, 'html')
12
- else
13
- content_tag :div, id: 'fis-container', class: (config[:container_class] || '').to_s do
14
- fis_get_list(data, partial, 'html')
15
- end
16
- end
17
- config[:scrollContainer] ||= (config[:targetContainer] || 'body')
18
- config[:targetContainer] ||= 'fis-container'
19
- result += javascript_tag do
20
- "flexInfiniteScroll('#{config[:scrollContainer]}',#{config.to_json})".html_safe
21
- end
22
- result.html_safe
23
- end
24
-
25
- def fis_next_page(data, partial, config = {})
26
- data = kaminari_prepare(data) if config[:kaminari]
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
- result.html_safe
41
- end
42
-
43
- private
44
-
45
- def kaminari_prepare(data)
46
- {
47
- data: data,
48
- next_page: data.next_page
49
- }
50
- end
51
- end
52
- end