First of all: this is cool module for improving UX, but...

When I press add to cart - nothing happens. There is a response about some movement, but cart is not updated.

Also - there are extra fields, like quantity, which is nice, and... Modify price. How? Why???

Comments

PlayfulWolf created an issue.

subhojit777’s picture

There is a response about some movement, but cart is not updated.

do you see any message in the logs?

Also - there are extra fields, like quantity, which is nice, and... Modify price. How? Why???

You should be able to modify them via the display settings. Check the installation and usage section.

pavlo_dor’s picture

I also have a promble
My console ERROR:

Drupal.AjaxError {message: "↵ AJAX HTTP error occurred. ↵ Received HTTP code: 2 ... 2c388001846b803a4824e2867154ea0ed2d225f7cd452"}} ↵ ", name:" AjaxError "}
message: "↵ AJAX HTTP error occurred. HTTP Received HTTP code: 2"
name: "AjaxError"
__proto__: Error at http: //tehnika/core/misc/ajax.js? v = 8.8.3: 98: 32 at http: //tehnika/core/misc/ajax.js? v = 8.8.3: 655: 3

adeelnawaz’s picture

If you have any kind of custom JS code disable it 1st and check it again.

subhojit777’s picture

@pavlo_dor Also, can you put the whole error message. That one is truncated.

pavlo_dor’s picture

I use
drupal/core": "^8.8.0",
drupal/dc_ajax_add_cart": "1.x-dev",
drupal/facets": "1.x-dev",
drupal/facets_range_dropdowns": "^1.0",
"drupal/views_ajax_history": "^1.2",
"drupal/views_infinite_scroll": "1.x-dev",
and in vies AJAX is ON!!!
If I enable dc_ajax_add_cart and in viws - Product datasource: Variations - AJAX ADD TO CART FORM
I want to add a product to my cart - I'll get an error in console
Drupal.AjaxError {message: "↵ AJAX HTTP error occurred. ↵ Received HTTP code: 2 ... 2c388001846b803a4824e2867154ea0ed2d225f7cd452"}} ↵ ", name:" AjaxError "}
message: "↵ AJAX HTTP error occurred. HTTP Received HTTP code: 2"
name: "AjaxError"
__proto__: Error at http: //tehnika/core/misc/ajax.js? v = 8.8.3: 98: 32 at http: //tehnika/core/misc/ajax.js? v = 8.8.3: 655: 3

if I see on input add to cart

<div class="views-field views-field-variations-1"><span class="field-content">

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/themes/stable/templates/views/views-view-field.html.twig' -->


<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form.html.twig' -->
<form class="commerce-order-item-dc-ajax-add-cart-form-commerce-product-12382 commerce-order-item-dc-ajax-add-cart-form" data-drupal-selector="commerce-order-item-dc-ajax-add-cart-form-commerce-product-12382" action="/duhovki" method="post" id="commerce-order-item-dc-ajax-add-cart-form-commerce-product-12382" accept-charset="UTF-8" data-drupal-form-fields="edit-purchased-entity-0-target-id,edit-quantity-0-value,edit-unit-price-0-override,edit-unit-price-0-amount-number,edit-submit">
  

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'container' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->
<div class="field--type-entity-reference field--name-purchased-entity field--widget-entity-reference-autocomplete js-form-wrapper form-wrapper" data-drupal-selector="edit-purchased-entity-wrapper" id="edit-purchased-entity-wrapper">

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'field_multiple_value_form' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/field-multiple-value-form.html.twig' -->
      

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->
<div class="js-form-item form-item js-form-type-entity-autocomplete form-type-entity-autocomplete js-form-item-purchased-entity-0-target-id form-item-purchased-entity-0-target-id">
      

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element_label' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->
<label for="edit-purchased-entity-0-target-id" class="js-form-required form-required">Product variation</label>
<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->


        

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__textfield' -->
<!-- FILE NAME SUGGESTIONS:
   * input--textfield.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input data-drupal-selector="edit-purchased-entity-0-target-id" class="form-autocomplete form-text required ui-autocomplete-input" data-autocomplete-path="/entity_reference_autocomplete/commerce_product_variation/default/3X4fdgJx4Xs6oeXEFzFy6FjjnaKWGfxFaOwdpx7JnPA" type="text" id="edit-purchased-entity-0-target-id" name="purchased_entity[0][target_id]" value="FA5 844 JC IX HA (12382)" size="60" maxlength="1024" placeholder="" required="required" aria-required="true" autocomplete="off">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->


        </div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->


  
<!-- END OUTPUT from 'core/themes/classy/templates/form/field-multiple-value-form.html.twig' -->

</div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->



<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__hidden' -->
<!-- FILE NAME SUGGESTIONS:
   * input--hidden.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input autocomplete="off" type="hidden" name="form_build_id" value="form-sbCvwzQdp5pQ1dYoS1WRVt_5kxzG-i6q-WsLMteR2G8">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->



<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__hidden' -->
<!-- FILE NAME SUGGESTIONS:
   * input--hidden.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input type="hidden" name="form_token" value="mYu9mNOIBBjAEWpwUc6w0DfhIPGsttuJkyxsvJjLvqo">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->



<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__hidden' -->
<!-- FILE NAME SUGGESTIONS:
   * input--hidden.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input data-drupal-selector="edit-commerce-order-item-dc-ajax-add-cart-form-commerce-product-12382" type="hidden" name="form_id" value="commerce_order_item_dc_ajax_add_cart_form_commerce_product_12382">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->



<!-- THEME DEBUG -->
<!-- THEME HOOK: 'container' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->
<div class="field--type-decimal field--name-quantity field--widget-commerce-quantity js-form-wrapper form-wrapper" data-drupal-selector="edit-quantity-wrapper" id="edit-quantity-wrapper">

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'field_multiple_value_form' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/field-multiple-value-form.html.twig' -->
      

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->
<div class="js-form-item form-item js-form-type-number form-type-number js-form-item-quantity-0-value form-item-quantity-0-value">
      

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element_label' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->
<label for="edit-quantity-0-value">Quantity</label>
<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->


        

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__number' -->
<!-- FILE NAME SUGGESTIONS:
   * input--number.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input data-drupal-selector="edit-quantity-0-value" type="number" id="edit-quantity-0-value" name="quantity[0][value]" value="1" step="1" min="1" placeholder="" class="form-number">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->


        </div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->


  
<!-- END OUTPUT from 'core/themes/classy/templates/form/field-multiple-value-form.html.twig' -->

</div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->



<!-- THEME DEBUG -->
<!-- THEME HOOK: 'container' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->
<div class="field--type-commerce-price field--name-unit-price field--widget-commerce-unit-price js-form-wrapper form-wrapper" data-drupal-selector="edit-unit-price-wrapper" id="edit-unit-price-wrapper">

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'field_multiple_value_form' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/field-multiple-value-form.html.twig' -->
      

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->
<div class="js-form-item form-item js-form-type-checkbox form-type-checkbox js-form-item-unit-price-0-override form-item-unit-price-0-override">
        

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__checkbox' -->
<!-- FILE NAME SUGGESTIONS:
   * input--checkbox.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input data-drupal-selector="edit-unit-price-0-override" type="checkbox" id="edit-unit-price-0-override" name="unit_price[0][override]" value="1" class="form-checkbox">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->


        

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element_label' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->
<label for="edit-unit-price-0-override" class="option">Override the unit price</label>
<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->


      </div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->



<!-- THEME DEBUG -->
<!-- THEME HOOK: 'container' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->
<div data-drupal-selector="edit-unit-price-0-amount" class="form-type-commerce-price js-form-wrapper form-wrapper" data-drupal-states="{&quot;visible&quot;:{&quot;:input[name=\u0022unit_price[0][override]\u0022]&quot;:{&quot;checked&quot;:true}}}" id="edit-unit-price-0-amount" style="display: none;">

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->
<div class="js-form-item form-item js-form-type-commerce-number form-type-commerce-number js-form-item-unit-price-0-amount-number form-item-unit-price-0-amount-number">
      

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'form_element_label' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->
<label for="edit-unit-price-0-amount-number">Unit price</label>
<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element-label.html.twig' -->


        

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__textfield' -->
<!-- FILE NAME SUGGESTIONS:
   * input--textfield.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input data-drupal-selector="edit-unit-price-0-amount-number" type="text" id="edit-unit-price-0-amount-number" name="unit_price[0][amount][number]" value="8899,00" size="10" maxlength="128" placeholder="9,99" class="form-text">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->


      <span class="field-suffix">UAH</span>
        </div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/form-element.html.twig' -->

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__hidden' -->
<!-- FILE NAME SUGGESTIONS:
   * input--hidden.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input data-drupal-selector="edit-unit-price-0-amount-currency-code" type="hidden" name="unit_price[0][amount][currency_code]" value="UAH">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->

</div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->

  
<!-- END OUTPUT from 'core/themes/classy/templates/form/field-multiple-value-form.html.twig' -->

</div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->


<!-- THEME DEBUG -->
<!-- THEME HOOK: 'container' -->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->
<div data-drupal-selector="edit-actions" class="form-actions js-form-wrapper form-wrapper" id="edit-actions"><div id="commerce-order-item-dc-ajax-add-cart-form-commerce-product-12382-ajax-add-cart-wrapper">

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'input__submit' -->
<!-- FILE NAME SUGGESTIONS:
   * input--submit.html.twig
   x input.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->
<input class="use-ajax-submit button button--primary js-form-submit form-submit" data-drupal-selector="edit-submit" data-disable-refocus="true" type="submit" id="edit-submit" name="op" value="Купить">

<!-- END OUTPUT from 'core/themes/classy/templates/form/input.html.twig' -->

</div></div>

<!-- END OUTPUT from 'core/themes/classy/templates/form/container.html.twig' -->


</form>

<!-- END OUTPUT from 'core/themes/classy/templates/form/form.html.twig' -->


<!-- END OUTPUT from 'core/themes/stable/templates/views/views-view-field.html.twig' -->

</span></div>
pavlo_dor’s picture

my ajax.js

/**
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

(function ($, window, Drupal, drupalSettings) {
  Drupal.behaviors.AJAX = {
    attach: function attach(context, settings) {
      function loadAjaxBehavior(base) {
        var elementSettings = settings.ajax[base];
        if (typeof elementSettings.selector === 'undefined') {
          elementSettings.selector = '#' + base;
        }
        $(elementSettings.selector).once('drupal-ajax').each(function () {
          elementSettings.element = this;
          elementSettings.base = base;
          Drupal.ajax(elementSettings);
        });
      }

      Object.keys(settings.ajax || {}).forEach(function (base) {
        return loadAjaxBehavior(base);
      });

      Drupal.ajax.bindAjaxLinks(document.body);

      $('.use-ajax-submit').once('ajax').each(function () {
        var elementSettings = {};

        elementSettings.url = $(this.form).attr('action');

        elementSettings.setClick = true;

        elementSettings.event = 'click';

        elementSettings.progress = { type: 'throbber' };
        elementSettings.base = $(this).attr('id');
        elementSettings.element = this;

        Drupal.ajax(elementSettings);
      });
    },
    detach: function detach(context, settings, trigger) {
      if (trigger === 'unload') {
        Drupal.ajax.expired().forEach(function (instance) {
          Drupal.ajax.instances[instance.instanceIndex] = null;
        });
      }
    }
  };

  Drupal.AjaxError = function (xmlhttp, uri, customMessage) {
    var statusCode = void 0;
    var statusText = void 0;
    var responseText = void 0;
    if (xmlhttp.status) {
      statusCode = '\n' + Drupal.t('An AJAX HTTP error occurred.') + '\n' + Drupal.t('HTTP Result Code: !status', { '!status': xmlhttp.status });
    } else {
      statusCode = '\n' + Drupal.t('An AJAX HTTP request terminated abnormally.');
    }
    statusCode += '\n' + Drupal.t('Debugging information follows.');
    var pathText = '\n' + Drupal.t('Path: !uri', { '!uri': uri });
    statusText = '';

    try {
      statusText = '\n' + Drupal.t('StatusText: !statusText', {
        '!statusText': $.trim(xmlhttp.statusText)
      });
    } catch (e) {}

    responseText = '';

    try {
      responseText = '\n' + Drupal.t('ResponseText: !responseText', {
        '!responseText': $.trim(xmlhttp.responseText)
      });
    } catch (e) {}

    responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi, '');
    responseText = responseText.replace(/[\n]+\s+/g, '\n');

    var readyStateText = xmlhttp.status === 0 ? '\n' + Drupal.t('ReadyState: !readyState', {
      '!readyState': xmlhttp.readyState
    }) : '';

    customMessage = customMessage ? '\n' + Drupal.t('CustomMessage: !customMessage', {
      '!customMessage': customMessage
    }) : '';

    this.message = statusCode + pathText + statusText + customMessage + responseText + readyStateText;

    this.name = 'AjaxError';
  };

  Drupal.AjaxError.prototype = new Error();
  Drupal.AjaxError.prototype.constructor = Drupal.AjaxError;

  Drupal.ajax = function (settings) {
    if (arguments.length !== 1) {
      throw new Error('Drupal.ajax() function must be called with one configuration object only');
    }

    var base = settings.base || false;
    var element = settings.element || false;
    delete settings.base;
    delete settings.element;

    if (!settings.progress && !element) {
      settings.progress = false;
    }

    var ajax = new Drupal.Ajax(base, element, settings);
    ajax.instanceIndex = Drupal.ajax.instances.length;
    Drupal.ajax.instances.push(ajax);

    return ajax;
  };

  Drupal.ajax.instances = [];

  Drupal.ajax.expired = function () {
    return Drupal.ajax.instances.filter(function (instance) {
      return instance && instance.element !== false && !document.body.contains(instance.element);
    });
  };

  Drupal.ajax.bindAjaxLinks = function (element) {
    $(element).find('.use-ajax').once('ajax').each(function (i, ajaxLink) {
      var $linkElement = $(ajaxLink);

      var elementSettings = {
        progress: { type: 'throbber' },
        dialogType: $linkElement.data('dialog-type'),
        dialog: $linkElement.data('dialog-options'),
        dialogRenderer: $linkElement.data('dialog-renderer'),
        base: $linkElement.attr('id'),
        element: ajaxLink
      };
      var href = $linkElement.attr('href');

      if (href) {
        elementSettings.url = href;
        elementSettings.event = 'click';
      }
      Drupal.ajax(elementSettings);
    });
  };

  Drupal.Ajax = function (base, element, elementSettings) {
    var defaults = {
      event: element ? 'mousedown' : null,
      keypress: true,
      selector: base ? '#' + base : null,
      effect: 'none',
      speed: 'none',
      method: 'replaceWith',
      progress: {
        type: 'throbber',
        message: Drupal.t('Please wait...')
      },
      submit: {
        js: true
      }
    };

    $.extend(this, defaults, elementSettings);

    this.commands = new Drupal.AjaxCommands();

    this.instanceIndex = false;

    if (this.wrapper) {
      this.wrapper = '#' + this.wrapper;
    }

    this.element = element;

    this.element_settings = elementSettings;

    this.elementSettings = elementSettings;

    if (this.element && this.element.form) {
      this.$form = $(this.element.form);
    }

    if (!this.url) {
      var $element = $(this.element);
      if ($element.is('a')) {
        this.url = $element.attr('href');
      } else if (this.element && element.form) {
        this.url = this.$form.attr('action');
      }
    }

    var originalUrl = this.url;

    this.url = this.url.replace(/\/nojs(\/|$|\?|#)/, '/ajax$1');

    if (drupalSettings.ajaxTrustedUrl[originalUrl]) {
      drupalSettings.ajaxTrustedUrl[this.url] = true;
    }

    var ajax = this;

    ajax.options = {
      url: ajax.url,
      data: ajax.submit,
      beforeSerialize: function beforeSerialize(elementSettings, options) {
        return ajax.beforeSerialize(elementSettings, options);
      },
      beforeSubmit: function beforeSubmit(formValues, elementSettings, options) {
        ajax.ajaxing = true;
        return ajax.beforeSubmit(formValues, elementSettings, options);
      },
      beforeSend: function beforeSend(xmlhttprequest, options) {
        ajax.ajaxing = true;
        return ajax.beforeSend(xmlhttprequest, options);
      },
      success: function success(response, status, xmlhttprequest) {
        if (typeof response === 'string') {
          response = $.parseJSON(response);
        }

        if (response !== null && !drupalSettings.ajaxTrustedUrl[ajax.url]) {
          if (xmlhttprequest.getResponseHeader('X-Drupal-Ajax-Token') !== '1') {
            var customMessage = Drupal.t('The response failed verification so will not be processed.');
            return ajax.error(xmlhttprequest, ajax.url, customMessage);
          }
        }

        return ajax.success(response, status);
      },
      complete: function complete(xmlhttprequest, status) {
        ajax.ajaxing = false;
        if (status === 'error' || status === 'parsererror') {
          return ajax.error(xmlhttprequest, ajax.url);
        }
      },

      dataType: 'json',
      type: 'POST'
    };

    if (elementSettings.dialog) {
      ajax.options.data.dialogOptions = elementSettings.dialog;
    }

    var wrapper = 'drupal_' + (elementSettings.dialogType || 'ajax');
    if (elementSettings.dialogRenderer) {
      wrapper += '.' + elementSettings.dialogRenderer;
    }

    var queryParameter = Drupal.ajax.WRAPPER_FORMAT + '=' + wrapper;
    if (ajax.options.url.indexOf(Drupal.ajax.WRAPPER_FORMAT) === -1) {
      // Ensure that we have a valid URL by adding ? when no query parameter is
      // yet available, otherwise append using &.
      ajax.options.url += (ajax.options.url.indexOf('?') === -1) ? '?' : '&';
      ajax.options.url += queryParameter;
    } else {
      var regexPattern = new RegExp(Drupal.ajax.WRAPPER_FORMAT + '=[^&]*', 'i');
      ajax.options.url = ajax.options.url.replace(regexPattern, queryParameter);
    }

    $(ajax.element).on(elementSettings.event, function (event) {
      if (!drupalSettings.ajaxTrustedUrl[ajax.url] && !Drupal.url.isLocal(ajax.url)) {
        throw new Error(Drupal.t('The callback URL is not local and not trusted: !url', {
          '!url': ajax.url
        }));
      }
      return ajax.eventResponse(this, event);
    });

    if (elementSettings.keypress) {
      $(ajax.element).on('keypress', function (event) {
        return ajax.keypressResponse(this, event);
      });
    }

    if (elementSettings.prevent) {
      $(ajax.element).on(elementSettings.prevent, false);
    }
  };

  Drupal.ajax.WRAPPER_FORMAT = '_wrapper_format';

  Drupal.Ajax.AJAX_REQUEST_PARAMETER = '_drupal_ajax';

  Drupal.Ajax.prototype.execute = function () {
    if (this.ajaxing) {
      return;
    }

    try {
      this.beforeSerialize(this.element, this.options);

      return $.ajax(this.options);
    } catch (e) {
      this.ajaxing = false;
      window.alert('An error occurred while attempting to process ' + this.options.url + ': ' + e.message);

      return $.Deferred().reject();
    }
  };

  Drupal.Ajax.prototype.keypressResponse = function (element, event) {
    var ajax = this;

    if (event.which === 13 || event.which === 32 && element.type !== 'text' && element.type !== 'textarea' && element.type !== 'tel' && element.type !== 'number') {
      event.preventDefault();
      event.stopPropagation();
      $(element).trigger(ajax.elementSettings.event);
    }
  };

  Drupal.Ajax.prototype.eventResponse = function (element, event) {
    event.preventDefault();
    event.stopPropagation();

    var ajax = this;

    if (ajax.ajaxing) {
      return;
    }

    try {
      if (ajax.$form) {
        if (ajax.setClick) {
          element.form.clk = element;
        }

        ajax.$form.ajaxSubmit(ajax.options);
      } else {
        ajax.beforeSerialize(ajax.element, ajax.options);
        $.ajax(ajax.options);
      }
    } catch (e) {
      ajax.ajaxing = false;
      window.alert('An error occurred while attempting to process ' + ajax.options.url + ': ' + e.message);
    }
  };

  Drupal.Ajax.prototype.beforeSerialize = function (element, options) {
    if (this.$form && document.body.contains(this.$form.get(0))) {
      var settings = this.settings || drupalSettings;
      Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize');
    }

    options.data[Drupal.Ajax.AJAX_REQUEST_PARAMETER] = 1;

    var pageState = drupalSettings.ajaxPageState;
    options.data['ajax_page_state[theme]'] = pageState.theme;
    options.data['ajax_page_state[theme_token]'] = pageState.theme_token;
    options.data['ajax_page_state[libraries]'] = pageState.libraries;
  };

  Drupal.Ajax.prototype.beforeSubmit = function (formValues, element, options) {};

  Drupal.Ajax.prototype.beforeSend = function (xmlhttprequest, options) {
    if (this.$form) {
      options.extraData = options.extraData || {};

      options.extraData.ajax_iframe_upload = '1';

      var v = $.fieldValue(this.element);
      if (v !== null) {
        options.extraData[this.element.name] = v;
      }
    }

    $(this.element).prop('disabled', true);

    if (!this.progress || !this.progress.type) {
      return;
    }

    var progressIndicatorMethod = 'setProgressIndicator' + this.progress.type.slice(0, 1).toUpperCase() + this.progress.type.slice(1).toLowerCase();
    if (progressIndicatorMethod in this && typeof this[progressIndicatorMethod] === 'function') {
      this[progressIndicatorMethod].call(this);
    }
  };

  Drupal.theme.ajaxProgressThrobber = function (message) {
    var messageMarkup = typeof message === 'string' ? Drupal.theme('ajaxProgressMessage', message) : '';
    var throbber = '<div class="throbber">&nbsp;</div>';

    return '<div class="ajax-progress ajax-progress-throbber">' + throbber + messageMarkup + '</div>';
  };

  Drupal.theme.ajaxProgressIndicatorFullscreen = function () {
    return '<div class="ajax-progress ajax-progress-fullscreen">&nbsp;</div>';
  };

  Drupal.theme.ajaxProgressMessage = function (message) {
    return '<div class="message">' + message + '</div>';
  };

  Drupal.theme.ajaxProgressBar = function ($element) {
    return $('<div class="ajax-progress ajax-progress-bar"></div>').append($element);
  };

  Drupal.Ajax.prototype.setProgressIndicatorBar = function () {
    var progressBar = new Drupal.ProgressBar('ajax-progress-' + this.element.id, $.noop, this.progress.method, $.noop);
    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 = $(Drupal.theme('ajaxProgressBar', progressBar.element));
    this.progress.object = progressBar;
    $(this.element).after(this.progress.element);
  };

  Drupal.Ajax.prototype.setProgressIndicatorThrobber = function () {
    this.progress.element = $(Drupal.theme('ajaxProgressThrobber', this.progress.message));
    $(this.element).after(this.progress.element);
  };

  Drupal.Ajax.prototype.setProgressIndicatorFullscreen = function () {
    this.progress.element = $(Drupal.theme('ajaxProgressIndicatorFullscreen'));
    $('body').append(this.progress.element);
  };

  Drupal.Ajax.prototype.success = function (response, status) {
    var _this = this;

    if (this.progress.element) {
      $(this.progress.element).remove();
    }
    if (this.progress.object) {
      this.progress.object.stopMonitoring();
    }
    $(this.element).prop('disabled', false);

    var elementParents = $(this.element).parents('[data-drupal-selector]').addBack().toArray();

    var focusChanged = false;
    Object.keys(response || {}).forEach(function (i) {
      if (response[i].command && _this.commands[response[i].command]) {
        _this.commands[response[i].command](_this, response[i], status);
        if (response[i].command === 'invoke' && response[i].method === 'focus') {
          focusChanged = true;
        }
      }
    });

    if (!focusChanged && this.element && !$(this.element).data('disable-refocus')) {
      var target = false;

      for (var n = elementParents.length - 1; !target && n >= 0; n--) {
        target = document.querySelector('[data-drupal-selector="' + elementParents[n].getAttribute('data-drupal-selector') + '"]');
      }

      if (target) {
        $(target).trigger('focus');
      }
    }

    if (this.$form && document.body.contains(this.$form.get(0))) {
      var settings = this.settings || drupalSettings;
      Drupal.attachBehaviors(this.$form.get(0), settings);
    }

    this.settings = null;
  };

  Drupal.Ajax.prototype.getEffect = function (response) {
    var type = response.effect || this.effect;
    var speed = response.speed || this.speed;

    var effect = {};
    if (type === 'none') {
      effect.showEffect = 'show';
      effect.hideEffect = 'hide';
      effect.showSpeed = '';
    } else if (type === 'fade') {
      effect.showEffect = 'fadeIn';
      effect.hideEffect = 'fadeOut';
      effect.showSpeed = speed;
    } else {
      effect.showEffect = type + 'Toggle';
      effect.hideEffect = type + 'Toggle';
      effect.showSpeed = speed;
    }

    return effect;
  };

  Drupal.Ajax.prototype.error = function (xmlhttprequest, uri, customMessage) {
    if (this.progress.element) {
      $(this.progress.element).remove();
    }
    if (this.progress.object) {
      this.progress.object.stopMonitoring();
    }

    $(this.wrapper).show();

    $(this.element).prop('disabled', false);

    if (this.$form && document.body.contains(this.$form.get(0))) {
      var settings = this.settings || drupalSettings;
      Drupal.attachBehaviors(this.$form.get(0), settings);
    }
    throw new Drupal.AjaxError(xmlhttprequest, uri, customMessage);
  };

  Drupal.theme.ajaxWrapperNewContent = function ($newContent, ajax, response) {
    return (response.effect || ajax.effect) !== 'none' && $newContent.filter(function (i) {
      return !($newContent[i].nodeName === '#comment' || $newContent[i].nodeName === '#text' && /^(\s|\n|\r)*$/.test($newContent[i].textContent));
    }).length > 1 ? Drupal.theme('ajaxWrapperMultipleRootElements', $newContent) : $newContent;
  };

  Drupal.theme.ajaxWrapperMultipleRootElements = function ($elements) {
    return $('<div></div>').append($elements);
  };

  Drupal.AjaxCommands = function () {};
  Drupal.AjaxCommands.prototype = {
    insert: function insert(ajax, response) {
      var $wrapper = response.selector ? $(response.selector) : $(ajax.wrapper);
      var method = response.method || ajax.method;
      var effect = ajax.getEffect(response);

      var settings = response.settings || ajax.settings || drupalSettings;

      var $newContent = $($.parseHTML(response.data, document, true));

      $newContent = Drupal.theme('ajaxWrapperNewContent', $newContent, ajax, response);

      switch (method) {
        case 'html':
        case 'replaceWith':
        case 'replaceAll':
        case 'empty':
        case 'remove':
          Drupal.detachBehaviors($wrapper.get(0), settings);
          break;
        default:
          break;
      }

      $wrapper[method]($newContent);

      if (effect.showEffect !== 'show') {
        $newContent.hide();
      }

      var $ajaxNewContent = $newContent.find('.ajax-new-content');
      if ($ajaxNewContent.length) {
        $ajaxNewContent.hide();
        $newContent.show();
        $ajaxNewContent[effect.showEffect](effect.showSpeed);
      } else if (effect.showEffect !== 'show') {
        $newContent[effect.showEffect](effect.showSpeed);
      }

      if ($newContent.parents('html').length) {
        $newContent.each(function (index, element) {
          if (element.nodeType === Node.ELEMENT_NODE) {
            Drupal.attachBehaviors(element, settings);
          }
        });
      }
    },
    remove: function remove(ajax, response, status) {
      var settings = response.settings || ajax.settings || drupalSettings;
      $(response.selector).each(function () {
        Drupal.detachBehaviors(this, settings);
      }).remove();
    },
    changed: function changed(ajax, response, status) {
      var $element = $(response.selector);
      if (!$element.hasClass('ajax-changed')) {
        $element.addClass('ajax-changed');
        if (response.asterisk) {
          $element.find(response.asterisk).append(' <abbr class="ajax-changed" title="' + Drupal.t('Changed') + '">*</abbr> ');
        }
      }
    },
    alert: function alert(ajax, response, status) {
      window.alert(response.text, response.title);
    },
    announce: function announce(ajax, response) {
      if (response.priority) {
        Drupal.announce(response.text, response.priority);
      } else {
        Drupal.announce(response.text);
      }
    },
    redirect: function redirect(ajax, response, status) {
      window.location = response.url;
    },
    css: function css(ajax, response, status) {
      $(response.selector).css(response.argument);
    },
    settings: function settings(ajax, response, status) {
      var ajaxSettings = drupalSettings.ajax;

      if (ajaxSettings) {
        Drupal.ajax.expired().forEach(function (instance) {

          if (instance.selector) {
            var selector = instance.selector.replace('#', '');
            if (selector in ajaxSettings) {
              delete ajaxSettings[selector];
            }
          }
        });
      }

      if (response.merge) {
        $.extend(true, drupalSettings, response.settings);
      } else {
        ajax.settings = response.settings;
      }
    },
    data: function data(ajax, response, status) {
      $(response.selector).data(response.name, response.value);
    },
    invoke: function invoke(ajax, response, status) {
      var $element = $(response.selector);
      $element[response.method].apply($element, _toConsumableArray(response.args));
    },
    restripe: function restripe(ajax, response, status) {
      $(response.selector).find('> tbody > tr:visible, > tr:visible').removeClass('odd even').filter(':even').addClass('odd').end().filter(':odd').addClass('even');
    },
    update_build_id: function update_build_id(ajax, response, status) {
      $('input[name="form_build_id"][value="' + response.old + '"]').val(response.new);
    },
    add_css: function add_css(ajax, response, status) {
      $('head').prepend(response.data);

      var match = void 0;
      var importMatch = /^@import url\("(.*)"\);$/gim;
      if (document.styleSheets[0].addImport && importMatch.test(response.data)) {
        importMatch.lastIndex = 0;
        do {
          match = importMatch.exec(response.data);
          document.styleSheets[0].addImport(match[1]);
        } while (match);
      }
    },
    message: function message(ajax, response) {
      var messages = new Drupal.Message(document.querySelector(response.messageWrapperQuerySelector));
      if (response.clearPrevious) {
        messages.clear();
      }
      messages.add(response.message, response.messageOptions);
    }
  };
})(jQuery, window, Drupal, drupalSettings);