renderedtext/render_async

View on GitHub
app/views/render_async/_request_jquery.js.erb

Summary

Maintainability
Test Coverage
if (window.jQuery) {
  (function($) {
    <% if turbolinks %>
    if (document.documentElement.hasAttribute("data-turbolinks-preview")) {
      return;
    }
    <% end %>
    <% if turbo %>
    if (document.documentElement.hasAttribute("data-turbo-preview")) {
      return;
    }
    <% end %>
    function createEvent(name, container) {
      var event = undefined;
      if (typeof(Event) === 'function') {
        event = new Event(name);
      } else {
        event = document.createEvent('Event');
        event.initEvent(name, true, true);
      }
      event.container = container
      return event;
    }

    function _runAfterDocumentLoaded(callback) {
      if (document.readyState === 'complete' || document.readyState === 'interactive') {
        // Handle a case where nested partials get loaded after the document loads
        callback();
      } else {
        <% if turbolinks %>
        $(document).one('turbolinks:load', callback);
        <% elsif turbo %>
        $(document).one('turbo:load', callback);
        <% else %>
        $(document).ready(callback);
        <% end %>
      }
    }

    function _makeRequest(currentRetryCount) {
      var headers = <%= headers.to_json.html_safe %>;
      var csrfTokenElement = document.querySelector('meta[name="csrf-token"]');
      if (csrfTokenElement)
        headers['X-CSRF-Token'] = csrfTokenElement.content;

      <% if retry_count_header %>
      if (typeof(currentRetryCount) === 'number') {
        headers['<%= retry_count_header.html_safe %>'] = currentRetryCount;
      }
      <% end %>

      $.ajax({
        url: '<%= path.html_safe %>',
        method: '<%= method %>',
        data: "<%= escape_javascript(data.to_s.html_safe) %>",
        headers: headers
      }).done(function(response) {
        var container = $("#<%= container_id %>");

        // If user navigated away before the request completed
        if (!container.length) return;

        <% if !interval && replace_container %>
          container.replaceWith(response);
        <% else %>
          container.empty();
          container.append(response);
        <% end %>

        var loadEvent = createEvent('render_async_load', container);
        document.dispatchEvent(loadEvent);

        <% if event_name.present? %>
          var event = createEvent("<%= event_name %>", container)
          document.dispatchEvent(event);
        <% end %>
      }).fail(function(response) {
        var skipErrorMessage = false;
        <% if retry_count > 0 %>
        skipErrorMessage = retry(currentRetryCount)
        <% end %>

        if (skipErrorMessage) return;

        var container = $("#<%= container_id %>");
        if (!container.length) return;

        container.replaceWith("<%= error_message.try(:html_safe) %>");

        var errorEvent = createEvent(
          "<%= error_event_name || 'render_async_error' %>",
          container
        )
        errorEvent.retryCount = currentRetryCount

        document.dispatchEvent(errorEvent);
      });
    };

    <% if retry_count > 0 %>
    var _retryMakeRequest = _makeRequest

    <% if retry_delay %>
    _retryMakeRequest = function(currentRetryCount) {
      setTimeout(function() {
        _makeRequest(currentRetryCount)
      }, <%= retry_delay %>)
    }
    <% else %>
    _retryMakeRequest = _makeRequest
    <% end %>

    function retry(currentRetryCount) {
      if (typeof(currentRetryCount) === 'number') {
        if (currentRetryCount >= <%= retry_count %>)
          return false;

        _retryMakeRequest(currentRetryCount + 1);
        return true;
      }

      _retryMakeRequest(1);
      return true;
    }
    <% end %>

    var _renderAsyncFunction = _makeRequest;

    var _interval;
    <% if interval %>
    var _renderAsyncFunction = function() {
      // If interval is already set, return
      if (typeof(_interval) === 'number') return

      _makeRequest();
      _interval = setInterval(_makeRequest, <%= interval %>);
    }

    var _clearRenderAsyncInterval = function() {
      if (typeof(_interval) === 'number'){
        clearInterval(_interval)
        _interval = undefined;
      }
    }

    function _setUpControlEvents() {
      var container = $("#<%= container_id %>");

      // Register a stop polling event on the container
      $(container).on('async-stop', _clearRenderAsyncInterval)

      // Register a start polling event on the container
      $(container).on('async-start', _renderAsyncFunction)
    }

    _runAfterDocumentLoaded(_setUpControlEvents)

    <% if turbolinks %>
    $(document).one('turbolinks:visit', _clearRenderAsyncInterval);
    <% end %>
    <% if turbo %>
    $(document).one('turbo:visit', _clearRenderAsyncInterval);
    <% end %>
    <% end %>

    <% if !replace_container %>
    function _setUpRefreshEvent() {
      var container = $("#<%= container_id %>");

      $(container).on('refresh', _renderAsyncFunction)
    }

    _runAfterDocumentLoaded(_setUpRefreshEvent)
    <% end %>

    <% if toggle %>
    function _setUpToggle() {
      $(document).<%= toggle[:once] ? 'one' : 'on' %>('<%= toggle[:event] || 'click' %>', '<%= toggle[:selector] %>', function(event) {
        if (typeof(_interval) === 'number') {
          clearInterval(_interval);
          _interval = undefined;
        } else {
          _renderAsyncFunction();
        }
      });

      <% if toggle[:start] %>
      _renderAsyncFunction()
      <% end %>
    }

    _runAfterDocumentLoaded(_setUpToggle);
    <% elsif !toggle %>
    _runAfterDocumentLoaded(_renderAsyncFunction)
    <% end %>
  }(jQuery));
} else {
  console.warn("Looks like you've enabled jQuery for render_async, but jQuery is not defined on the window object");
};