diff --git a/ckan/public-bs2/base/javascript/modules/basic-form.js b/ckan/public-bs2/base/javascript/modules/basic-form.js
index d1e97a4ce95..a3c57b094a1 100644
--- a/ckan/public-bs2/base/javascript/modules/basic-form.js
+++ b/ckan/public-bs2/base/javascript/modules/basic-form.js
@@ -2,7 +2,23 @@ this.ckan.module('basic-form', function (jQuery) {
return {
initialize: function () {
var message = this._('There are unsaved modifications to this form');
+
+ $.proxyAll(this, /_on/);
+
this.el.incompleteFormWarning(message);
+
+ // Disable the submit button on form submit, to prevent multiple
+ // consecutive form submissions.
+ this.el.on('submit', this._onSubmit);
+ },
+ _onSubmit() {
+
+ // The button is not disabled immediately so that its value can be sent
+ // the first time the form is submitted, because the "save" field is
+ // used in the backend.
+ setTimeout(function() {
+ this.el.find('button[name="save"]').attr('disabled', true);
+ }.bind(this), 0);
}
};
});
diff --git a/ckan/public-bs2/base/test/spec/modules/basic-form.spec.js b/ckan/public-bs2/base/test/spec/modules/basic-form.spec.js
index 3153c44b7b6..9d0628fc86b 100644
--- a/ckan/public-bs2/base/test/spec/modules/basic-form.spec.js
+++ b/ckan/public-bs2/base/test/spec/modules/basic-form.spec.js
@@ -5,9 +5,11 @@ describe('ckan.module.BasicFormModule()', function () {
beforeEach(function () {
sinon.stub(jQuery.fn, 'incompleteFormWarning');
- this.el = document.createElement('button');
+ this.el = document.createElement('form');
+ this.el.innerHTML = ''
this.sandbox = ckan.sandbox();
this.sandbox.body = this.fixture;
+ this.sandbox.body.append(this.el)
this.module = new BasicFormModule(this.el, {}, this.sandbox);
});
@@ -21,5 +23,17 @@ describe('ckan.module.BasicFormModule()', function () {
this.module.initialize();
assert.called(jQuery.fn.incompleteFormWarning);
});
+
+ it('should disable the submit button on form submit', function(done) {
+ this.module.initialize();
+ this.module._onSubmit();
+
+ setTimeout(function() {
+ var buttonAttrDisabled = this.el.querySelector('button').getAttribute('disabled');
+
+ assert.ok(buttonAttrDisabled === 'disabled')
+ done();
+ }.bind(this), 0);
+ });
});
});
diff --git a/ckan/public/base/javascript/modules/basic-form.js b/ckan/public/base/javascript/modules/basic-form.js
index d1e97a4ce95..a3c57b094a1 100644
--- a/ckan/public/base/javascript/modules/basic-form.js
+++ b/ckan/public/base/javascript/modules/basic-form.js
@@ -2,7 +2,23 @@ this.ckan.module('basic-form', function (jQuery) {
return {
initialize: function () {
var message = this._('There are unsaved modifications to this form');
+
+ $.proxyAll(this, /_on/);
+
this.el.incompleteFormWarning(message);
+
+ // Disable the submit button on form submit, to prevent multiple
+ // consecutive form submissions.
+ this.el.on('submit', this._onSubmit);
+ },
+ _onSubmit() {
+
+ // The button is not disabled immediately so that its value can be sent
+ // the first time the form is submitted, because the "save" field is
+ // used in the backend.
+ setTimeout(function() {
+ this.el.find('button[name="save"]').attr('disabled', true);
+ }.bind(this), 0);
}
};
});
diff --git a/ckan/public/base/test/spec/modules/basic-form.spec.js b/ckan/public/base/test/spec/modules/basic-form.spec.js
index 3153c44b7b6..9d0628fc86b 100644
--- a/ckan/public/base/test/spec/modules/basic-form.spec.js
+++ b/ckan/public/base/test/spec/modules/basic-form.spec.js
@@ -5,9 +5,11 @@ describe('ckan.module.BasicFormModule()', function () {
beforeEach(function () {
sinon.stub(jQuery.fn, 'incompleteFormWarning');
- this.el = document.createElement('button');
+ this.el = document.createElement('form');
+ this.el.innerHTML = ''
this.sandbox = ckan.sandbox();
this.sandbox.body = this.fixture;
+ this.sandbox.body.append(this.el)
this.module = new BasicFormModule(this.el, {}, this.sandbox);
});
@@ -21,5 +23,17 @@ describe('ckan.module.BasicFormModule()', function () {
this.module.initialize();
assert.called(jQuery.fn.incompleteFormWarning);
});
+
+ it('should disable the submit button on form submit', function(done) {
+ this.module.initialize();
+ this.module._onSubmit();
+
+ setTimeout(function() {
+ var buttonAttrDisabled = this.el.querySelector('button').getAttribute('disabled');
+
+ assert.ok(buttonAttrDisabled === 'disabled')
+ done();
+ }.bind(this), 0);
+ });
});
});