diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index b1b2a9dc40..e8a387746d 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -4,6 +4,8 @@ Changelog
1.6 (xx.xx.xxxx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~
+ * Image upload form in image chooser now performs client side validation so that the selected file is not lost in the submission (Jack Paine)
+
1.5 (xx.xx.xxxx)
~~~~~~~~~~~~~~~~
diff --git a/docs/releases/1.6.rst b/docs/releases/1.6.rst
index b68f86626d..b3d02a5be2 100644
--- a/docs/releases/1.6.rst
+++ b/docs/releases/1.6.rst
@@ -14,6 +14,8 @@ What's new
Minor features
~~~~~~~~~~~~~~
+ * Image upload form in image chooser now performs client side validation so that the selected file is not lost in the submission (Jack Paine)
+
Bug fixes
~~~~~~~~~
diff --git a/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js b/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js
index 3d973e1aad..03d8ec56a4 100644
--- a/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js
+++ b/wagtail/wagtailadmin/static_src/wagtailadmin/js/core.js
@@ -221,15 +221,23 @@ $(function() {
var $self = $(this);
var $replacementElem = $('em', $self);
var reEnableAfter = 30;
- var dataName = 'disabledtimeout'
+ var dataName = 'disabledtimeout';
- // Check the form this submit button belongs to (if any)
+ // Perform client-side validation on the form this submit button belongs to (if any)
var form = $self.closest('form').get(0);
- if (form && form.checkValidity && (form.checkValidity() == false)) {
- // ^ Check form.checkValidity returns something as it may not be browser compatible
+ if (form && form.checkValidity && (!form.checkValidity())) {
+ // form exists, browser provides a checkValidity method and checkValidity returns false
return;
}
+ window.cancelSpinner = function() {
+ $self.prop('disabled', '').removeData(dataName).removeClass('button-longrunning-active');
+
+ if ($self.data('clicked-text')) {
+ $replacementElem.text($self.data('original-text'));
+ }
+ };
+
// Disabling a button prevents it submitting the form, so disabling
// must occur on a brief timeout only after this function returns.
@@ -240,11 +248,7 @@ $(function() {
$self.data(dataName, setTimeout(function() {
clearTimeout($self.data(dataName));
- $self.prop('disabled', '').removeData(dataName).removeClass('button-longrunning-active')
-
- if ($self.data('clicked-text')) {
- $replacementElem.text($self.data('original-text'));
- }
+ cancelSpinner();
}, reEnableAfter * 1000));
diff --git a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js
index 30e07e1b5c..01e7bdb7aa 100644
--- a/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js
+++ b/wagtail/wagtailimages/templates/wagtailimages/chooser/chooser.js
@@ -59,25 +59,26 @@ function(modal) {
$('form.image-upload', modal.body).submit(function() {
var formdata = new FormData(this);
- $.ajax({
- url: this.action,
- data: formdata,
- processData: false,
- contentType: false,
- type: 'POST',
- dataType: 'text',
- success: function(response){
- modal.loadResponseText(response);
- },
- error: function(response, textStatus, errorThrown) {
- {% trans "Server Error" as error_label %}
- {% trans "Report this error to your webmaster with the following information:" as error_message %}
- message = '{{ error_message|escapejs }}
' + errorThrown + ' - ' + response.status;
- $('#upload').append(
- '