Maybe we could improve the way(s) developers can implement custom progress indicators.

What do you think about the following code which is a refactored version of the current 8.x-dev code:

Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) {
  // ...
  // Insert progress indicator
  var progressIndicatorMethod = 'setProgressIndicator' + this.progress.type.slice(0,1).toUpperCase() + this.progress.type.slice(1).toLowerCase();
  if (this[progressIndicatorMethod] && this[progressIndicatorMethod].call) {
    this[progressIndicatorMethod].call(this);
    $(this.element).after(this.progress.element);
  }
};

So we simply factor out the method for the existing progress indicators, having the side effect of allowing custom progress indicators:

Drupal.ajax.prototype.setProgressIndicatorProgressbar = function() {
  var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
  if (this.progress.message) {
    progressBar.setProgress(-1, this.progress.message);
  }
  if (this.progress.url) {
    progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500);
  }
  this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar');
  this.progress.object = progressBar;
};
Drupal.ajax.prototype.setProgressIndicatorThrobber = function() {
  this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
  if (this.progress.message) {
    $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
  }
  $(this.element).after(this.progress.element);
};

This way developers can use their custom progress indicators simply by using:

  $form = array(
    'element' => array(
      '#type' => 'textfield',
      '#ajax' => array(
        'callback' => 'mymodule_ajax_callback',
        'wrapper' => 'ajax-wrapper',
        'progress' => array(
          'type' => 'custom'
          // Additional custom options
        ),
      ),
    ),
  );

And then implementing:

Drupal.ajax.prototype.setProgressIndicatorCustom = function() {
  // Setting this.progress.element is the only necessary thing to happen in here.
  this.progress.element = $('<div class="ajax-progress ajax-progress-custom">indicator</div>');
};

Comments

nod_’s picture

Issue tags: +JavaScript clean-up

+1 for cleaning this up.

nod_’s picture

nod_’s picture

Issue summary: View changes

fixed a typo in code

kalidasan’s picture

If we want to place progress bar "before" or "after" any element, please use below code.

      '#ajax' => array(
        'callback' => 'mymodule_ajax_callback',
        'wrapper' => 'ajax-wrapper',
        'progress' => array(
          'type' => 'custom'
          'before' => 'class_name' or 'after' => 'some-id'
        ),
      ),
  Drupal.ajax.prototype.setProgressIndicatorCustom = function() {
    this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
    if (this.progress.message) {
      $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>');
    }
    if (this.progress.after) {
      $(this.progress.after).append(this.progress.element);
    }
    if (this.progress.before) {
      $(this.progress.before).prepend(this.progress.element);
    }
  };