From beb3734c54b9bec595442db2f65102a849ab5033 Mon Sep 17 00:00:00 2001 From: Naveed Ahmad Date: Tue, 30 Jul 2019 06:57:18 +0500 Subject: [PATCH] Added lazy render #34 --- app/views/render_async/_lazy_load.js.erb | 21 +++++++++++++ app/views/render_async/_render_async.html.erb | 2 ++ app/views/render_async/_request_jquery.js.erb | 31 ++++++++++++++----- .../render_async/_request_vanilla.js.erb | 20 ++++++++++-- lib/render_async/view_helper.rb | 4 ++- 5 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 app/views/render_async/_lazy_load.js.erb diff --git a/app/views/render_async/_lazy_load.js.erb b/app/views/render_async/_lazy_load.js.erb new file mode 100644 index 0000000..d542b07 --- /dev/null +++ b/app/views/render_async/_lazy_load.js.erb @@ -0,0 +1,21 @@ +var lazyLoaded = function(element) { + element.setAttribute("data-loaded", true) +} + +var isLazyLoaded = function (element) { + return "true" === element.getAttribute("data-loaded") +}; +var _lazyListener = function () { + var observer = new IntersectionObserver(function (entries, observer) { + entries.forEach(function (entry) { + if(0 < entry.intersectionRatio || entry.isIntersecting){ + if(!isLazyLoaded(entry.target)){ + _listener(); + observer.unobserve(entry.target); + } + } + }) + }, {rootMargin: '0px', threshold: 0}); + + observer.observe(document.getElementById("<%= container_id %>")) +} \ No newline at end of file diff --git a/app/views/render_async/_render_async.html.erb b/app/views/render_async/_render_async.html.erb index 63db9a0..902f638 100644 --- a/app/views/render_async/_render_async.html.erb +++ b/app/views/render_async/_render_async.html.erb @@ -20,6 +20,7 @@ error_event_name: error_event_name, retry_count: retry_count, interval: interval, + lazy_load: lazy_load, turbolinks: RenderAsync.configuration.turbolinks } %> <% else %> <%= render partial: 'render_async/request_vanilla', @@ -34,6 +35,7 @@ error_event_name: error_event_name, retry_count: retry_count, interval: interval, + lazy_load: lazy_load, turbolinks: RenderAsync.configuration.turbolinks } %> <% end %> <% end %> diff --git a/app/views/render_async/_request_jquery.js.erb b/app/views/render_async/_request_jquery.js.erb index 904465b..6ebfba1 100644 --- a/app/views/render_async/_request_jquery.js.erb +++ b/app/views/render_async/_request_jquery.js.erb @@ -5,7 +5,6 @@ if (window.jQuery) { return; } <% end %> - var _listener = function(currentRetryCount) { var headers = <%= headers.to_json.html_safe %>; var csrfTokenElement = document.querySelector('meta[name="csrf-token"]') @@ -18,7 +17,9 @@ if (window.jQuery) { data: "<%= escape_javascript(data.to_s.html_safe) %>", headers: headers }).done(function(response) { - <% if interval %> + lazyLoaded(document.getElementById("<%= container_id %>")); + + <% if interval %> $("#<%= container_id %>").empty(); $("#<%= container_id %>").append(response); <% else %> @@ -73,16 +74,30 @@ if (window.jQuery) { } <% end %> + <% if lazy_load %> + <%= render partial: 'render_async/lazy_load', + formats: [:js], + locals: { container_id: container_id } %> + <% end %> + <% if turbolinks %> - $(document).one('turbolinks:load', _listener); + <% if lazy_load %> + $(document).one('turbolinks:load', _lazyListener); + <% else %> + $(document).one('turbolinks:load', _listener); + <% end %> <% elsif interval %> - var _intervalFunction = function() { - _listener(); - setInterval(_listener, <%= interval %>); - } + var _intervalFunction = function() { + _listener(); + setInterval(_listener, <%= interval %>); + } $(document).ready(_intervalFunction); <% else %> - $(document).ready(_listener); + <% if lazy_load %> + $(document).ready(_lazyListener); + <% else %> + $(document).ready(_listener); + <% end %> <% end %> }(jQuery)); } else { diff --git a/app/views/render_async/_request_vanilla.js.erb b/app/views/render_async/_request_vanilla.js.erb index 2ded337..c629f51 100644 --- a/app/views/render_async/_request_vanilla.js.erb +++ b/app/views/render_async/_request_vanilla.js.erb @@ -26,6 +26,8 @@ if (request.readyState === 4) { if (request.status >= SUCCESS && request.status < ERROR) { var container = document.getElementById('<%= container_id %>'); + lazyLoaded(container); + <% if interval %> container.innerHTML = request.response; <% else %> @@ -86,10 +88,20 @@ } <% end %> + <% if lazy_load %> + <%= render partial: 'render_async/lazy_load', + formats: [:js], + locals: { container_id: container_id } %> + <% end %> + <% if turbolinks %> document.addEventListener("turbolinks:load", function (e) { e.target.removeEventListener(e.type, arguments.callee); - _listener.call(this); + <% if lazy_load %> + _lazyListener(); + <% else %> + _listener.call(this); + <% end %> }); <% elsif interval %> var _intervalFunction = function() { @@ -98,6 +110,10 @@ } document.addEventListener("DOMContentLoaded", _intervalFunction); <% else %> - document.addEventListener("DOMContentLoaded", _listener); + <% if lazy_load %> + document.addEventListener("DOMContentLoaded", _lazyListener); + <% else %> + document.addEventListener("DOMContentLoaded", _listener); + <% end %> <% end %> })(); diff --git a/lib/render_async/view_helper.rb b/lib/render_async/view_helper.rb index 720eada..38b6e26 100644 --- a/lib/render_async/view_helper.rb +++ b/lib/render_async/view_helper.rb @@ -30,6 +30,7 @@ def render_async(path, options = {}, &placeholder) error_event_name = options.delete(:error_event_name) retry_count = options.delete(:retry_count) || 0 interval = options.delete(:interval) + lazy_load = options.delete(:lazy_load) || false render 'render_async/render_async', html_element_name: html_element_name, container_id: container_id, @@ -44,7 +45,8 @@ def render_async(path, options = {}, &placeholder) error_message: error_message, error_event_name: error_event_name, retry_count: retry_count, - interval: interval + interval: interval, + lazy_load: lazy_load end private