Merge pull request #9794 from edx/efischer/prevent_doubleclick
TNL 3294 - Prevent double click creating multiple teams
This commit is contained in:
@@ -7,8 +7,8 @@
|
||||
"common/js/components/views/feedback_prompt"],
|
||||
function ($, _, gettext, NotificationView, PromptView) {
|
||||
var toggleExpandCollapse, showLoadingIndicator, hideLoadingIndicator, confirmThenRunOperation,
|
||||
runOperationShowingMessage, disableElementWhileRunning, getScrollOffset, setScrollOffset,
|
||||
setScrollTop, redirect, reload, hasChangedAttributes, deleteNotificationHandler,
|
||||
runOperationShowingMessage, withDisabledElement, disableElementWhileRunning,
|
||||
getScrollOffset, setScrollOffset, setScrollTop, redirect, reload, hasChangedAttributes, deleteNotificationHandler,
|
||||
validateRequiredField, validateURLItemEncoding, validateTotalKeyLength, checkTotalKeyLengthViolations;
|
||||
|
||||
// see https://openedx.atlassian.net/browse/TNL-889 for what is it and why it's 65
|
||||
@@ -87,6 +87,25 @@
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Wraps a Backbone event callback to disable the event's target element.
|
||||
*
|
||||
* This paradigm is designed to be used in Backbone event maps where
|
||||
* multiple events firing simultaneously is not desired.
|
||||
*
|
||||
* @param functionName the function to execute, as a string.
|
||||
* The function must return a jQuery promise and be able to take an event
|
||||
*/
|
||||
withDisabledElement = function(functionName) {
|
||||
return function(event) {
|
||||
var view = this;
|
||||
disableElementWhileRunning($(event.currentTarget), function() {
|
||||
//call view.functionName(event), with view as the current this
|
||||
return view[functionName].apply(view, [event]);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Disables a given element when a given operation is running.
|
||||
* @param {jQuery} element the element to be disabled.
|
||||
@@ -235,6 +254,7 @@
|
||||
'hideLoadingIndicator': hideLoadingIndicator,
|
||||
'confirmThenRunOperation': confirmThenRunOperation,
|
||||
'runOperationShowingMessage': runOperationShowingMessage,
|
||||
'withDisabledElement': withDisabledElement,
|
||||
'disableElementWhileRunning': disableElementWhileRunning,
|
||||
'deleteNotificationHandler': deleteNotificationHandler,
|
||||
'setScrollTop': setScrollTop,
|
||||
|
||||
@@ -17,6 +17,29 @@ define(["jquery", "underscore", "common/js/components/utils/view_utils", "common
|
||||
deferred.resolve();
|
||||
expect(link).not.toHaveClass("is-disabled");
|
||||
});
|
||||
|
||||
it("uses withDisabledElement wrapper to disable element while running a Backbone event handler", function() {
|
||||
var link,
|
||||
eventCallback,
|
||||
event,
|
||||
deferred = new $.Deferred(),
|
||||
promise = deferred.promise(),
|
||||
MockView = Backbone.View.extend({
|
||||
testFunction: function() {
|
||||
return promise;
|
||||
}
|
||||
}),
|
||||
testView = new MockView();
|
||||
setFixtures("<a href='#' id='link'>ripe apples drop about my head</a>");
|
||||
link = $("#link");
|
||||
expect(link).not.toHaveClass("is-disabled");
|
||||
eventCallback = ViewUtils.withDisabledElement('testFunction');
|
||||
event = {currentTarget: link};
|
||||
eventCallback.apply(testView, [event]);
|
||||
expect(link).toHaveClass("is-disabled");
|
||||
deferred.resolve();
|
||||
expect(link).not.toHaveClass("is-disabled");
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress notification", function() {
|
||||
@@ -92,4 +115,4 @@ define(["jquery", "underscore", "common/js/components/utils/view_utils", "common
|
||||
});
|
||||
});
|
||||
});
|
||||
}).call(this, define || RequireJS.define);
|
||||
}).call(this, define || RequireJS.define);
|
||||
|
||||
@@ -6,16 +6,17 @@
|
||||
'gettext',
|
||||
'js/views/fields',
|
||||
'teams/js/models/team',
|
||||
'common/js/components/utils/view_utils',
|
||||
'text!teams/templates/edit-team.underscore'],
|
||||
function (Backbone, _, gettext, FieldViews, TeamModel, editTeamTemplate) {
|
||||
function (Backbone, _, gettext, FieldViews, TeamModel, ViewUtils, editTeamTemplate) {
|
||||
return Backbone.View.extend({
|
||||
|
||||
maxTeamNameLength: 255,
|
||||
maxTeamDescriptionLength: 300,
|
||||
|
||||
events: {
|
||||
'click .action-primary': 'createOrUpdateTeam',
|
||||
'submit form': 'createOrUpdateTeam',
|
||||
'click .action-primary': ViewUtils.withDisabledElement('createOrUpdateTeam'),
|
||||
'submit form': ViewUtils.withDisabledElement('createOrUpdateTeam'),
|
||||
'click .action-cancel': 'cancelAndGoBack'
|
||||
},
|
||||
|
||||
@@ -124,10 +125,9 @@
|
||||
var validationResult = this.validateTeamData(data);
|
||||
if (validationResult.status === false) {
|
||||
this.showMessage(validationResult.message, validationResult.srMessage);
|
||||
return;
|
||||
return $().promise();
|
||||
}
|
||||
|
||||
this.teamModel.save(data, saveOptions)
|
||||
return view.teamModel.save(data, saveOptions)
|
||||
.done(function(result) {
|
||||
view.teamEvents.trigger('teams:update', {
|
||||
action: view.action,
|
||||
|
||||
Reference in New Issue
Block a user