diff --git a/core/misc/ajax.es6.js b/core/misc/ajax.es6.js index 6248e46efe..eb450916d9 100644 --- a/core/misc/ajax.es6.js +++ b/core/misc/ajax.es6.js @@ -531,6 +531,29 @@ 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 })); } + + // If an Ajax element is a form submission element, perform client-side + // validation if the element doesn't explicitly call for a validation + // bypass. If the form is invalid: + // - If the browser has an implementation of + // HTMLFormElement.reportValidity(), use this to trigger native + // validation messages, otherwise, fall back to triggering a form + // submission. + // - Don't generate a response. + let $elem = $(this); + if ($elem.attr('type') === 'submit' && !$elem.attr('formnovalidate')) { + let formElem = $elem.closest('form')[0]; + if (formElem && !formElem.checkValidity()) { + if (typeof formElem.reportValidity === 'function') { + formElem.reportValidity(); + } + else { + $elem.once(`${event.type}-ajax`).trigger(event.type); + } + return; + } + } + return ajax.eventResponse(this, event); }); diff --git a/core/misc/ajax.js b/core/misc/ajax.js index 5ea52425be..f7f494ffef 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -252,6 +252,20 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr 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 })); } + + var $elem = $(this); + if ($elem.attr('type') === 'submit' && !$elem.attr('formnovalidate')) { + var formElem = $elem.closest('form')[0]; + if (formElem && !formElem.checkValidity()) { + if (typeof formElem.reportValidity === 'function') { + formElem.reportValidity(); + } else { + $elem.once(event.type + '-ajax').trigger(event.type); + } + return; + } + } + return ajax.eventResponse(this, event); });