Quantcast
Channel: Issues for Drupal core
Viewing all articles
Browse latest Browse all 294447

If a custom beforeSubmit() or beforeSend() function on a Drupal.ajax object returns false, 'ajaxing' gets stuck as true

$
0
0

I was working with a file upload field (<input type ="file" />) in a Webform form today, and noticed that clicking on the "Upload" submit input before I had selected a file didn't prevent the AJAX upload code from running. While this didn't break anything, it was confusing to see the throbber there and I wanted a way to prevent the AJAX submit from happening in the first place and display a "Please select a file" message to the user.

Upon investigating core's ajax.js I found Drupal.ajax.prototype.beforeSubmit(), left empty for easy overriding. I also saw in jquery.form.js that there's a check for the beforeSubmit function returning false, which is expressly for the purpose of preventing the form submission from going through.

So I implemented a custom beforeSubmit function for the submit button which returns false if the file input is empty. On first run, it worked as expected, but thereafter, clicking on the submit button appeared to do nothing whatsoever - not even run the beforeSubmit function again.

I figured out that the following sequence had happened (where "ajax" is the Drupal.ajax object for my HTML submit element):

  1. Leaving file field blank, I click the upload button.
  2. ajax.eventResponse() runs, calling ajaxSubmit() (in jquery.form.js) on the form.
  3. Within ajaxSubmit(), ajax.options.beforeSubmit() sets ajax.ajaxing = true, then calls ajax.beforeSubmit().
  4. My beforeSubmit() function returns false.
  5. Back in ajaxSubmit(), the returned false value is detected and ajaxSubmit() ends right then.
  6. I select a file (or even don't; irrelevant) and click the upload button again.
  7. Again, ajax.eventResponse() runs. But now, ajax.ajaxing is still true from the first attempt, and eventResponse() immediately returns false.

This if (ajax.ajaxing) check is intended to prevent multiple ajax requests from overlapping each other. But in this sequence, since ajaxSubmit() never finished the first time, ajax.ajaxing doesn't get reset to false, and no further attempts to submit will go through.

My rough fix would be to adjust the default ajax.options.beforeSubmit() around line 150 of ajax.js to something like:

beforeSubmit: function (form_values, element_settings, options) {
  ajax.ajaxing = true;
  // If beforeSubmit() aborts the submit, reset ajaxing flag.
  var continue = ajax.beforeSubmit(form_values, element_settings, options);
  if (!continue) {
    ajax.ajaxing = false;
  }
  return continue;

In the meantime I was able to work around this simply by setting ajaxing back to false if my beforeSubmit() function was going to return false.


Viewing all articles
Browse latest Browse all 294447

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>