render_async 2.1.5 → 2.1.10

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.
@@ -5,38 +5,32 @@
5
5
  <%= placeholder %>
6
6
  </<%= html_element_name %>>
7
7
 
8
- <% content_for :render_async do %>
8
+ <% content_for content_for_name do %>
9
9
  <%= javascript_tag html_options do %>
10
+ <% locals = { container_id: container_id,
11
+ replace_container: replace_container,
12
+ path: path,
13
+ method: method,
14
+ data: data,
15
+ event_name: event_name,
16
+ toggle: toggle,
17
+ headers: headers,
18
+ error_message: error_message,
19
+ error_event_name: error_event_name,
20
+ retry_count: retry_count,
21
+ retry_delay: retry_delay,
22
+ interval: interval,
23
+ turbolinks: RenderAsync.configuration.turbolinks,
24
+ turbo: RenderAsync.configuration.turbo} %>
25
+
10
26
  <% if RenderAsync.configuration.jquery %>
11
27
  <%= render partial: 'render_async/request_jquery',
12
28
  formats: [:js],
13
- locals: { container_id: container_id,
14
- path: path,
15
- method: method,
16
- data: data,
17
- event_name: event_name,
18
- toggle: toggle,
19
- headers: headers,
20
- error_message: error_message,
21
- error_event_name: error_event_name,
22
- retry_count: retry_count,
23
- interval: interval,
24
- turbolinks: RenderAsync.configuration.turbolinks } %>
29
+ locals: locals %>
25
30
  <% else %>
26
31
  <%= render partial: 'render_async/request_vanilla',
27
32
  formats: [:js],
28
- locals: { container_id: container_id,
29
- path: path,
30
- method: method,
31
- data: data,
32
- event_name: event_name,
33
- toggle: toggle,
34
- headers: headers,
35
- error_message: error_message,
36
- error_event_name: error_event_name,
37
- retry_count: retry_count,
38
- interval: interval,
39
- turbolinks: RenderAsync.configuration.turbolinks } %>
33
+ locals: locals %>
40
34
  <% end %>
41
35
  <% end %>
42
36
  <% end %>
@@ -5,6 +5,11 @@ if (window.jQuery) {
5
5
  return;
6
6
  }
7
7
  <% end %>
8
+ <% if turbo %>
9
+ if (document.documentElement.hasAttribute("data-turbo-preview")) {
10
+ return;
11
+ }
12
+ <% end %>
8
13
  function createEvent(name, container) {
9
14
  var event = undefined;
10
15
  if (typeof(Event) === 'function') {
@@ -18,11 +23,18 @@ if (window.jQuery) {
18
23
  }
19
24
 
20
25
  function _runAfterDocumentLoaded(callback) {
21
- <% if turbolinks %>
22
- $(document).one('turbolinks:load', callback);
23
- <% else %>
24
- $(document).ready(callback);
25
- <% end %>
26
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
27
+ // Handle a case where nested partials get loaded after the document loads
28
+ callback();
29
+ } else {
30
+ <% if turbolinks %>
31
+ $(document).one('turbolinks:load', callback);
32
+ <% elsif turbo %>
33
+ $(document).one('turbo:load', callback);
34
+ <% else %>
35
+ $(document).ready(callback);
36
+ <% end %>
37
+ }
26
38
  }
27
39
 
28
40
  function _makeRequest(currentRetryCount) {
@@ -38,11 +50,15 @@ if (window.jQuery) {
38
50
  headers: headers
39
51
  }).done(function(response) {
40
52
  var container = $("#<%= container_id %>");
41
- <% if interval %>
53
+
54
+ // If user navigated away before the request completed
55
+ if (!container.length) return;
56
+
57
+ <% if !interval && replace_container %>
58
+ container.replaceWith(response);
59
+ <% else %>
42
60
  container.empty();
43
61
  container.append(response);
44
- <% else %>
45
- container.replaceWith(response);
46
62
  <% end %>
47
63
 
48
64
  var loadEvent = createEvent('render_async_load', container);
@@ -61,48 +77,97 @@ if (window.jQuery) {
61
77
  if (skipErrorMessage) return;
62
78
 
63
79
  var container = $("#<%= container_id %>");
80
+ if (!container.length) return;
81
+
64
82
  container.replaceWith("<%= error_message.try(:html_safe) %>");
65
83
 
66
- var errorEvent = createEvent('render_async_error', container);
67
- errorEvent.container = container;
68
- document.dispatchEvent(errorEvent);
84
+ var errorEvent = createEvent(
85
+ "<%= error_event_name || 'render_async_error' %>",
86
+ container
87
+ )
88
+ errorEvent.retryCount = currentRetryCount
69
89
 
70
- <% if error_event_name.present? %>
71
- var event = createEvent("<%= error_event_name %>", container)
72
- document.dispatchEvent(event);
73
- <% end %>
90
+ document.dispatchEvent(errorEvent);
74
91
  });
75
92
  };
76
93
 
77
94
  <% if retry_count > 0 %>
95
+ var _retryMakeRequest = _makeRequest
96
+
97
+ <% if retry_delay %>
98
+ _retryMakeRequest = function(currentRetryCount) {
99
+ setTimeout(function() {
100
+ _makeRequest(currentRetryCount)
101
+ }, <%= retry_delay %>)
102
+ }
103
+ <% end %>
104
+
78
105
  function retry(currentRetryCount) {
79
106
  if (typeof(currentRetryCount) === 'number') {
80
107
  if (currentRetryCount >= <%= retry_count %>)
81
108
  return false;
82
109
 
83
- _makeRequest(currentRetryCount + 1);
110
+ _retryMakeRequest(currentRetryCount + 1);
84
111
  return true;
85
112
  }
86
113
 
87
- _makeRequest(1);
114
+ _retryMakeRequest(1);
88
115
  return true;
89
116
  }
90
117
  <% end %>
91
118
 
92
119
  var _renderAsyncFunction = _makeRequest;
93
120
 
94
- <% if interval %>
95
121
  var _interval;
122
+ <% if interval %>
96
123
  var _renderAsyncFunction = function() {
124
+ // If interval is already set, return
125
+ if (typeof(_interval) === 'number') return
126
+
97
127
  _makeRequest();
98
128
  _interval = setInterval(_makeRequest, <%= interval %>);
99
129
  }
130
+
131
+ var _clearRenderAsyncInterval = function() {
132
+ if (typeof(_interval) === 'number'){
133
+ clearInterval(_interval)
134
+ _interval = undefined;
135
+ }
136
+ }
137
+
138
+ function _setUpControlEvents() {
139
+ var container = $("#<%= container_id %>");
140
+
141
+ // Register a stop polling event on the container
142
+ $(container).on('async-stop', _clearRenderAsyncInterval)
143
+
144
+ // Register a start polling event on the container
145
+ $(container).on('async-start', _renderAsyncFunction)
146
+ }
147
+
148
+ _runAfterDocumentLoaded(_setUpControlEvents)
149
+
150
+ <% if turbolinks %>
151
+ $(document).one('turbolinks:visit', _clearRenderAsyncInterval);
152
+ <% end %>
153
+ <% if turbo %>
154
+ $(document).one('turbo:visit', _clearRenderAsyncInterval);
155
+ <% end %>
156
+ <% end %>
157
+
158
+ <% if !replace_container %>
159
+ function _setUpRefreshEvent() {
160
+ var container = $("#<%= container_id %>");
161
+
162
+ $(container).on('refresh', _renderAsyncFunction)
163
+ }
164
+
165
+ _runAfterDocumentLoaded(_setUpRefreshEvent)
100
166
  <% end %>
101
167
 
102
168
  <% if toggle %>
103
169
  function _setUpToggle() {
104
170
  $(document).<%= toggle[:once] ? 'one' : 'on' %>('<%= toggle[:event] || 'click' %>', '<%= toggle[:selector] %>', function(event) {
105
- event.preventDefault();
106
171
  if (typeof(_interval) === 'number') {
107
172
  clearInterval(_interval);
108
173
  _interval = undefined;
@@ -110,13 +175,17 @@ if (window.jQuery) {
110
175
  _renderAsyncFunction();
111
176
  }
112
177
  });
178
+
179
+ <% if toggle[:start] %>
180
+ _renderAsyncFunction()
181
+ <% end %>
113
182
  }
114
183
 
115
- _runAfterDocumentLoaded(_setUpToggle)
184
+ _runAfterDocumentLoaded(_setUpToggle);
116
185
  <% elsif !toggle %>
117
186
  _runAfterDocumentLoaded(_renderAsyncFunction)
118
187
  <% end %>
119
188
  }(jQuery));
120
189
  } else {
121
- console.warn("Looks like you've enabled jQuery for render_async, but jQuery is not defined");
190
+ console.warn("Looks like you've enabled jQuery for render_async, but jQuery is not defined on the window object");
122
191
  };
@@ -4,6 +4,11 @@
4
4
  return;
5
5
  }
6
6
  <% end %>
7
+ <% if turbo %>
8
+ if (document.documentElement.hasAttribute("data-turbo-preview")) {
9
+ return;
10
+ }
11
+ <% end %>
7
12
  function createEvent(name, container) {
8
13
  var event = undefined;
9
14
  if (typeof(Event) === 'function') {
@@ -22,6 +27,11 @@
22
27
  e.target.removeEventListener(e.type, arguments.callee);
23
28
  callback();
24
29
  });
30
+ <% elsif turbo %>
31
+ document.addEventListener("turbo:load", function(e) {
32
+ e.target.removeEventListener(e.type, arguments.callee);
33
+ callback();
34
+ });
25
35
  <% else %>
26
36
  document.addEventListener("DOMContentLoaded", callback);
27
37
  <% end %>
@@ -44,14 +54,20 @@
44
54
  request.setRequestHeader(key, headers[key]);
45
55
  });
46
56
 
57
+ request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
58
+
47
59
  request.onreadystatechange = function() {
48
60
  if (request.readyState === 4) {
49
61
  if (request.status >= SUCCESS && request.status < ERROR) {
50
62
  var container = document.getElementById('<%= container_id %>');
51
- <% if interval %>
52
- container.innerHTML = request.response;
53
- <% else %>
63
+
64
+ // If user navigated away before the request completed
65
+ if (!container) return;
66
+
67
+ <% if !interval && replace_container %>
54
68
  container.outerHTML = request.response;
69
+ <% else %>
70
+ container.innerHTML = request.response;
55
71
  <% end %>
56
72
 
57
73
  var loadEvent = createEvent('render_async_load', container);
@@ -70,16 +86,17 @@
70
86
  if (skipErrorMessage) return;
71
87
 
72
88
  var container = document.getElementById('<%= container_id %>');
89
+ if (!container) return;
90
+
73
91
  container.outerHTML = '<%= error_message.try(:html_safe) %>';
74
92
 
75
- console.log(container)
76
- var errorEvent = createEvent('render_async_error', container);
77
- document.dispatchEvent(errorEvent);
93
+ var errorEvent = createEvent(
94
+ "<%= error_event_name || 'render_async_error' %>",
95
+ container
96
+ );
97
+ errorEvent.retryCount = currentRetryCount
78
98
 
79
- <% if error_event_name.present? %>
80
- var event = createEvent('<%= error_event_name %>', container);
81
- document.dispatchEvent(event);
82
- <% end %>
99
+ document.dispatchEvent(errorEvent);
83
100
  }
84
101
  }
85
102
  };
@@ -89,35 +106,82 @@
89
106
  };
90
107
 
91
108
  <% if retry_count > 0 %>
109
+
110
+ <% if retry_delay %>
111
+ _retryMakeRequest = function(currentRetryCount) {
112
+ setTimeout(function() {
113
+ _makeRequest(currentRetryCount)
114
+ }, <%= retry_delay %>)
115
+ }
116
+ <% end %>
117
+
92
118
  function retry(currentRetryCount) {
93
119
  if (typeof(currentRetryCount) === 'number') {
94
120
  if (currentRetryCount >= <%= retry_count %>)
95
121
  return false;
96
122
 
97
- _makeRequest(currentRetryCount + 1);
123
+ _retryMakeRequest(currentRetryCount + 1);
98
124
  return true;
99
125
  }
100
126
 
101
- _makeRequest(1);
127
+ _retryMakeRequest(1);
102
128
  return true;
103
129
  }
104
130
  <% end %>
105
131
 
106
132
  var _renderAsyncFunction = _makeRequest;
107
133
 
108
- <% if interval %>
109
134
  var _interval;
135
+ <% if interval %>
110
136
  var _renderAsyncFunction = function() {
137
+ // If interval is already set, return
138
+ if (typeof(_interval) === 'number') return
139
+
111
140
  _makeRequest();
112
141
  _interval = setInterval(_makeRequest, <%= interval %>);
113
142
  }
143
+
144
+ var _clearRenderAsyncInterval = function() {
145
+ if (typeof(_interval) === 'number'){
146
+ clearInterval(_interval)
147
+ _interval = undefined;
148
+ }
149
+ }
150
+
151
+ function _setUpControlEvents() {
152
+ var container = document.getElementById('<%= container_id %>');
153
+
154
+ // Register a polling stop event on the container
155
+ container.addEventListener("async-stop", _clearRenderAsyncInterval)
156
+
157
+ // Register a start polling event on the container
158
+ container.addEventListener("async-start", _renderAsyncFunction)
159
+ }
160
+
161
+ _runAfterDocumentLoaded(_setUpControlEvents)
162
+
163
+ <% if turbolinks %>
164
+ document.addEventListener("turbolinks:visit", _clearRenderAsyncInterval)
165
+ <% end %>
166
+ <% if turbo %>
167
+ document.addEventListener("turbo:visit", _clearRenderAsyncInterval)
168
+ <% end %>
169
+ <% end %>
170
+
171
+ <% if !replace_container %>
172
+ function _setUpRefreshEvent() {
173
+ var container = document.getElementById('<%= container_id %>');
174
+
175
+ container.addEventListener('refresh', _renderAsyncFunction)
176
+ }
177
+
178
+ _runAfterDocumentLoaded(_setUpRefreshEvent)
114
179
  <% end %>
115
180
 
116
181
  <% if toggle %>
117
182
  function _setUpToggle() {
118
- var selectors = document.querySelectorAll('<%= toggle[:selector] %>'), i;
183
+ var selectors = document.querySelectorAll('<%= toggle[:selector] %>');
119
184
  var handler = function(event) {
120
- event.preventDefault();
121
185
  if (typeof(_interval) === 'number') {
122
186
  clearInterval(_interval);
123
187
  _interval = undefined;
@@ -129,7 +193,11 @@
129
193
  <% end %>
130
194
  };
131
195
 
132
- for (i = 0; i < selectors.length; ++i) {
196
+ <% if toggle[:start] %>
197
+ _renderAsyncFunction()
198
+ <% end %>
199
+
200
+ for (var i = 0; i < selectors.length; ++i) {
133
201
  selectors[i].addEventListener('<%= toggle[:event] || 'click' %>', handler)
134
202
  }
135
203
  }
@@ -11,3 +11,10 @@ cd spec/fixtures/rails-5-base-app
11
11
  ls
12
12
  bundle install
13
13
  bundle exec cucumber
14
+
15
+ cd ../../../spec/fixtures/rails-6-base-app
16
+ ls
17
+ bundle install
18
+ yarn install
19
+ RAILS_ENV=test bundle exec rails webpacker:compile
20
+ bundle exec cucumber
@@ -1,10 +1,13 @@
1
1
  module RenderAsync
2
2
  class Configuration
3
- attr_accessor :jquery, :turbolinks
3
+ attr_accessor :jquery, :turbolinks, :turbo, :replace_container, :nonces
4
4
 
5
5
  def initialize
6
6
  @jquery = false
7
7
  @turbolinks = false
8
+ @turbo = false
9
+ @replace_container = true
10
+ @nonces = false
8
11
  end
9
12
  end
10
13
  end
@@ -1,3 +1,3 @@
1
1
  module RenderAsync
2
- VERSION = "2.1.5".freeze
2
+ VERSION = "2.1.10".freeze
3
3
  end
@@ -2,7 +2,6 @@ require 'securerandom'
2
2
 
3
3
  module RenderAsync
4
4
  module ViewHelper
5
-
6
5
  def render_async_cache_key(path)
7
6
  "render_async_#{path}"
8
7
  end
@@ -20,18 +19,17 @@ module RenderAsync
20
19
  def render_async(path, options = {}, &placeholder)
21
20
  event_name = options.delete(:event_name)
22
21
  placeholder = capture(&placeholder) if block_given?
23
- retry_count = options.delete(:retry_count) || 0
24
- html_options = options.delete(:html_options) || {}
25
22
 
26
23
  render 'render_async/render_async', **container_element_options(options),
27
24
  path: path,
28
- html_options: html_options,
25
+ html_options: html_options(options),
29
26
  event_name: event_name,
30
27
  placeholder: placeholder,
31
28
  **request_options(options),
32
29
  **error_handling_options(options),
33
- retry_count: retry_count,
34
- **polling_options(options)
30
+ **retry_options(options),
31
+ **polling_options(options),
32
+ **content_for_options(options)
35
33
  end
36
34
 
37
35
  private
@@ -39,7 +37,16 @@ module RenderAsync
39
37
  def container_element_options(options)
40
38
  { html_element_name: options[:html_element_name] || 'div',
41
39
  container_id: options[:container_id] || generate_container_id,
42
- container_class: options[:container_class] }
40
+ container_class: options[:container_class],
41
+ replace_container: replace_container(options) }
42
+ end
43
+
44
+ def html_options(options)
45
+ set_options = options.delete(:html_options) || {}
46
+
47
+ set_options[:nonce] = configuration.nonces if set_options[:nonce].nil?
48
+
49
+ set_options
43
50
  end
44
51
 
45
52
  def request_options(options)
@@ -53,15 +60,36 @@ module RenderAsync
53
60
  error_event_name: options[:error_event_name] }
54
61
  end
55
62
 
63
+ def retry_options(options)
64
+ {
65
+ retry_count: options.delete(:retry_count) || 0,
66
+ retry_delay: options.delete(:retry_delay)
67
+ }
68
+ end
69
+
56
70
  def polling_options(options)
57
71
  { interval: options[:interval],
58
72
  toggle: options[:toggle] }
59
73
  end
60
74
 
61
- private
75
+ def content_for_options(options)
76
+ {
77
+ content_for_name: options[:content_for_name] || :render_async
78
+ }
79
+ end
62
80
 
63
81
  def generate_container_id
64
82
  "render_async_#{SecureRandom.hex(5)}#{Time.now.to_i}"
65
83
  end
84
+
85
+ def replace_container(options)
86
+ return options[:replace_container] unless options[:replace_container].nil?
87
+
88
+ configuration.replace_container
89
+ end
90
+
91
+ def configuration
92
+ RenderAsync.configuration
93
+ end
66
94
  end
67
95
  end