Prevent multiple form submission on table row actions

This disables any table row actions that do a form submit after an
action is taken and the form is being submitted. It also changes the
cursor to make it clear an action is taking place.

Closes-Bug: #1433849
Change-Id: I004f0ae43e5201eba30ff38a34be680416407fbc
(cherry picked from commit ea2f6b35da)

Handle modals properly when disabling table actions

This fixes a problem when attempting to disable table actions on
a modal dialog. It causes the Launch Instance modal to render
incorrectly and other modals result in a
"$form.on is not a function" error displayed in the browser
console. This is because the modal init function is assuming the
argument passed in is a jQuery reference to the modal but in
reality it is just the modal DOM node itself. The problem is fixed
by making a jQuery reference to the modal before preparing to
disable the actions of any tables that might be displayed on it.

Closes-Bug: #1462544
Change-Id: I56399468ff5e2b5bcd0b285ece0d6dd001500c24
(cherry picked from commit 54ee33c4d8)
This commit is contained in:
Justin Pomeroy 2015-06-02 09:21:42 -05:00 committed by Doug Fish
parent 339016afdd
commit bafdabbb1f
2 changed files with 35 additions and 2 deletions

View File

@ -6,10 +6,15 @@ horizon.datatables = {
if ( rows_to_update > 0 ) {
var interval = $rows_to_update.attr('data-update-interval'),
$table = $rows_to_update.closest('table'),
submit_in_progress = $table.closest('form').attr('data-submitted'),
decay_constant = $table.attr('decay_constant');
// Do not update this row if the action column is expanded
if ($rows_to_update.find('.actions_column .btn-group.open').length) {
// Do not update this row if the action column is expanded or the form
// is in the process of being submitted. If we update the row while the
// form is still submitting any disabled action buttons would potentially
// be enabled again, allowing for multiple form submits.
if ($rows_to_update.find('.actions_column .btn-group.open').length ||
submit_in_progress) {
// Wait and try to update again in next interval instead
setTimeout(horizon.datatables.update, interval);
// Remove interval decay, since this will not hit server
@ -169,6 +174,24 @@ horizon.datatables = {
initialize_table_tooltips: function() {
$('div.table_wrapper').tooltip({selector: '[data-toggle="tooltip"]', container: 'body'});
},
disable_actions_on_submit: function($form) {
// This applies changes to the table form when a user takes an action that
// submits the form. It relies on the form being re-rendered after the
// submit is completed to remove these changes.
$form = $form || $(".table_wrapper > form");
$form.on("submit", function () {
// Add the 'submitted' flag to the form so the row update interval knows
// not to update the row and therefore re-enable the actions that we are
// disabling here.
$(this).attr('data-submitted', 'true');
// Disable row action buttons. This prevents multiple form submission.
$(this).find('td.actions_column button[type="submit"]').addClass("disabled");
// Use CSS to update the cursor so it's very clear that an action is
// in progress.
$(this).addClass('wait');
});
}
};
@ -560,6 +583,7 @@ horizon.addInitFunction(horizon.datatables.init = function() {
horizon.datatables.set_table_sorting($('body'));
horizon.datatables.set_table_query_filter($('body'));
horizon.datatables.set_table_fixed_filter($('body'));
horizon.datatables.disable_actions_on_submit();
// Also apply on tables in modal views.
horizon.modals.addModalInitFunction(horizon.datatables.add_table_checkboxes);
@ -567,6 +591,9 @@ horizon.addInitFunction(horizon.datatables.init = function() {
horizon.modals.addModalInitFunction(horizon.datatables.set_table_query_filter);
horizon.modals.addModalInitFunction(horizon.datatables.set_table_fixed_filter);
horizon.modals.addModalInitFunction(horizon.datatables.initialize_table_tooltips);
horizon.modals.addModalInitFunction(function modalInitActionDisable(modal) {
horizon.datatables.disable_actions_on_submit($(modal).find(".table_wrapper > form"));
});
// Also apply on tables in tabs views for lazy-loaded data.
horizon.tabs.addTabLoadFunction(horizon.datatables.add_table_checkboxes);
@ -577,6 +604,7 @@ horizon.addInitFunction(horizon.datatables.init = function() {
horizon.tabs.addTabLoadFunction(horizon.datatables.initialize_table_tooltips);
horizon.tabs.addTabLoadFunction(function(tab) {
horizon.datatables.validate_button($(tab).find(".table_wrapper > form"));
horizon.datatables.disable_actions_on_submit($(tab).find(".table_wrapper > form"));
});
horizon.datatables.update();

View File

@ -221,6 +221,11 @@ a.current_item:hover h4 {
padding: 0 0 0 1px;
}
.table_wrapper > form.wait,
.table_wrapper > form.wait * {
cursor: wait !important;
}
.table-bordered {
border: none;
}