flex_infinite_scroll 0.1.4 → 0.2.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 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