How to make sure my behavior is triggered before AJAX? I have a form elements that looks like this:

  $form['properties'][$property-&gt;idProperty] = array(
    '#title' =&gt; $property-&gt;Label,
    '#ajax' =&gt; array(
      'callback' =&gt; 'mymodule_filter_ajax',
      'wrapper' =&gt; 'mymodule-filter-result',
      'method' =&gt; 'replace',
      'effect' =&gt; 'fade',
    ),
    '#attributes' =&gt; array(
      'autocomplete' =&gt; 'off',
      'class' =&gt; array('exclusive'),
      'exclusivity_group' =&gt; array ( $property-&gt;ExclusivityGroup )
    ),
  );


The point of it is to have only one element from each group used at a time. To enforce that exclusivity, I created behavior like this:

(function($) { 
  Drupal.behaviors.behavior_name = {
    attach: function (context, settings) {

      $('select.exclusive', context).on('change', function(){
        // Make all not selected
        $("[exclusivity_group='"+$(this).attr('exclusivity_group')+"']").not(this).find("option").attr('selected', false);
        // select "all"
        $("[exclusivity_group='"+$(this).attr('exclusivity_group')+"']").not(this).find("option[value='all']").attr('selected', true);
      });
    }
  };
})(jQuery);


Note that both code blocks above are simplified, please don't criticize it too much as this is not actual code I'm using posted verbatim.

How can I make sure my behavior acts before AJAX? If it happens to act after AJAX, I may end up with two fields set to something other than 'all', and that's specifically what I wanted to avoid. I may use $triggering_element to detect if it was one of "exclusive" fields, and I probably will, even if only as a secondary precaution, but I would strongly prefer to have things happening right in the JavaScript part.



I tried using this answer, but I don't think I understand how it works. I tried:

  $('select.exclusive', context).each(function(){
    console.log($(this).attr('id'));
    Drupal.ajax[$(this).attr('id')].options.beforeSubmit = function (form_values, element, options) {
      console.log(element.html());
    };
  });


First console.log returns IDs as expected. And it works, beforeSend is, indeed, changed as it should, it's function gets executed when needed. Sadly console.log(element.html()); returns content of a whole form, not the triggering element of AJAX, so I'm not able to safely enforce exclusiveness - I don't know which element was changed last, so no way to select other elements.
I got it working now. The way to do it was:


Get all elements that are in "exclusive" groups using classes, .each over them
For each element, change beforeSubmit using $(this).attr('id') as index for ajax table
Because I was not able to get element to point to a specific element (it always pointed to entire form), I used helper variable at the beginning of .each loop.


Resulting code is like this:

(function($) { 
  Drupal.behaviors.behavior_name = {
    attach: function (context, settings) {

      $('select.exclusive', context).each(function(){
        var triggering_element = $(this);
        Drupal.ajax[$(this).attr('id')].options.beforeSubmit = function (form_values, element, options) {
          // Make all not selected
          $("[exclusivity_group='"+triggering_element.attr('exclusivity_group')+"']").not(triggering_element).find("option").attr('selected', false);
          // select "all"
          $("[exclusivity_group='"+triggering_element.attr('exclusivity_group')+"']").not(triggering_element).find("option[value='all']").attr('selected', true);

        };
      });
    }
  };
})(jQuery);