Commit a2e32218 by Stephen Sanchez

Merge pull request #553 from edx/sanchez/fix-multi-event-firing

Making event listener registering explicit for containers
parents 8bed9618 434f93ac
...@@ -22,6 +22,7 @@ describe("OpenAssessment.Container", function () { ...@@ -22,6 +22,7 @@ describe("OpenAssessment.Container", function () {
this.addHandler = function() {}; this.addHandler = function() {};
this.removeHandler = function() {}; this.removeHandler = function() {};
this.updateHandler = function() {}; this.updateHandler = function() {};
this.addEventListeners = function() {};
}; };
var container = null; var container = null;
...@@ -57,6 +58,9 @@ describe("OpenAssessment.Container", function () { ...@@ -57,6 +58,9 @@ describe("OpenAssessment.Container", function () {
// Create the container and configure it // Create the container and configure it
// to use the stub container item. // to use the stub container item.
container = createContainer(); container = createContainer();
// Explicitly add event listeners.
container.addEventListeners();
}); });
it("adds and removes items", function() { it("adds and removes items", function() {
...@@ -130,6 +134,19 @@ describe("OpenAssessment.Container", function () { ...@@ -130,6 +134,19 @@ describe("OpenAssessment.Container", function () {
expect(container.getItemValues().length).toEqual(1); expect(container.getItemValues().length).toEqual(1);
}); });
it("only creates one item when add is fired", function() {
// Initialize multiple containers without explicitly adding event
// listeners
createContainer();
createContainer();
createContainer();
// Press the add button
expect(container.getItemValues().length).toEqual(0);
$("#add_button").click();
expect(container.getItemValues().length).toEqual(1);
});
it("removes an element when the remove button is pressed", function() { it("removes an element when the remove button is pressed", function() {
// Add some items // Add some items
container.add(); container.add();
...@@ -158,6 +175,9 @@ describe("OpenAssessment.Container", function () { ...@@ -158,6 +175,9 @@ describe("OpenAssessment.Container", function () {
// Initialize the container object // Initialize the container object
container = createContainer(); container = createContainer();
// Explicitly add event listeners.
container.addEventListeners();
// Verify that the container recognizes the pre-existing item // Verify that the container recognizes the pre-existing item
expect(container.getItemValues()).toEqual([{ id: 0 }]); expect(container.getItemValues()).toEqual([{ id: 0 }]);
......
...@@ -73,29 +73,38 @@ OpenAssessment.Container = function(containerItem, kwargs) { ...@@ -73,29 +73,38 @@ OpenAssessment.Container = function(containerItem, kwargs) {
this.createContainerItem = function(element) { this.createContainerItem = function(element) {
return new containerItem(element, container.notifier); return new containerItem(element, container.notifier);
}; };
// Install a click handler for the add button
$(this.addButtonElement).click($.proxy(this.add, this));
// Find items already in the container and install click
// handlers for the delete buttons.
$("." + this.removeButtonClass, this.containerElement).click(
function(eventData) {
var item = container.createContainerItem(eventData.target);
container.remove(item);
}
);
// Initialize existing items, in case they need to install their
// own event handlers.
$("." + this.containerItemClass, this.containerElement).each(
function(index, element) {
container.createContainerItem(element);
}
);
}; };
OpenAssessment.Container.prototype = { OpenAssessment.Container.prototype = {
/**
Adds event listeners to the container and its children. Must be
called explicitly when the container is initially created.
*/
addEventListeners: function() {
var container = this;
// Install a click handler for the add button
$(this.addButtonElement).click($.proxy(this.add, this));
// Find items already in the container and install click
// handlers for the delete buttons.
$("." + this.removeButtonClass, this.containerElement).click(
function(eventData) {
var item = container.createContainerItem(eventData.target);
container.remove(item);
}
);
// Initialize existing items, in case they need to install their
// own event handlers.
$("." + this.containerItemClass, this.containerElement).each(
function(index, element) {
var item = container.createContainerItem(element);
item.addEventListeners();
}
);
},
/** /**
Adds a new item to the container. Adds a new item to the container.
**/ **/
...@@ -127,6 +136,7 @@ OpenAssessment.Container.prototype = { ...@@ -127,6 +136,7 @@ OpenAssessment.Container.prototype = {
// Initialize the item, allowing it to install event handlers. // Initialize the item, allowing it to install event handlers.
// Fire event handler for adding a new element // Fire event handler for adding a new element
var handlerItem = container.createContainerItem(containerItem); var handlerItem = container.createContainerItem(containerItem);
handlerItem.addEventListeners();
handlerItem.addHandler(); handlerItem.addHandler();
}, },
......
...@@ -69,7 +69,6 @@ Returns: ...@@ -69,7 +69,6 @@ Returns:
OpenAssessment.RubricOption = function(element, notifier) { OpenAssessment.RubricOption = function(element, notifier) {
this.element = element; this.element = element;
this.notifier = notifier; this.notifier = notifier;
$(this.element).focusout($.proxy(this.updateHandler, this));
}; };
OpenAssessment.RubricOption.prototype = { OpenAssessment.RubricOption.prototype = {
...@@ -177,6 +176,14 @@ OpenAssessment.RubricOption.prototype = { ...@@ -177,6 +176,14 @@ OpenAssessment.RubricOption.prototype = {
"points": optionPoints "points": optionPoints
} }
); );
},
/**
Adds event listeners specific to this container item.
*/
addEventListeners: function() {
// Install a focus out handler for container changes.
$(this.element).focusout($.proxy(this.updateHandler, this));
} }
}; };
...@@ -204,8 +211,6 @@ OpenAssessment.RubricCriterion = function(element, notifier) { ...@@ -204,8 +211,6 @@ OpenAssessment.RubricCriterion = function(element, notifier) {
notifier: this.notifier notifier: this.notifier
} }
); );
$(this.element).focusout($.proxy(this.updateHandler, this));
}; };
...@@ -255,6 +260,17 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -255,6 +260,17 @@ OpenAssessment.RubricCriterion.prototype = {
}, },
/** /**
Invoked by the container to add event listeners to all child containers
of this item, and add event listeners specific to this container item.
*/
addEventListeners: function() {
this.optionContainer.addEventListeners();
// Install a focus out handler for container changes.
$(this.element).focusout($.proxy(this.updateHandler, this));
},
/**
Add an option to the criterion. Add an option to the criterion.
Uses the client-side template to create the new option. Uses the client-side template to create the new option.
**/ **/
...@@ -343,6 +359,7 @@ OpenAssessment.TrainingExample.prototype = { ...@@ -343,6 +359,7 @@ OpenAssessment.TrainingExample.prototype = {
}, },
addHandler: function() {}, addHandler: function() {},
addEventListeners: function() {},
removeHandler: function() {}, removeHandler: function() {},
updateHandler: function() {} updateHandler: function() {}
}; };
\ No newline at end of file
...@@ -26,6 +26,7 @@ OpenAssessment.EditRubricView = function(element, notifier) { ...@@ -26,6 +26,7 @@ OpenAssessment.EditRubricView = function(element, notifier) {
notifier: notifier notifier: notifier
} }
); );
this.criteriaContainer.addEventListeners();
this.alert = new OpenAssessment.ValidationAlert($('#openassessment_rubric_validation_alert', this.element)); this.alert = new OpenAssessment.ValidationAlert($('#openassessment_rubric_validation_alert', this.element));
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment