Commit 9e6e0011 by Tim Krones

Address review comments.

parent 602d0212
......@@ -105,20 +105,33 @@ class TestVectorDraw(StudioEditableBaseTest):
def check_vector_properties(
self, menu, is_present=False, expected_label="Vector Properties",
expected_name=None, expected_tail=None, expected_length=None, expected_angle=None
expected_name=None, expected_tail=None, expected_length=None, expected_angle=None,
input_fields_disabled=True
):
if is_present:
vector_properties = menu.find_element_by_css_selector(".vector-properties")
vector_properties_label = vector_properties.find_element_by_css_selector("h3")
self.assertEquals(vector_properties_label.text, expected_label)
# Name
self.check_vector_property(vector_properties, "name", "select", "name:", expected_name or "-")
self.check_vector_property(
vector_properties, "name", "select", "name:", expected_name or "-",
field_disabled=input_fields_disabled
)
# Tail
self.check_vector_property(vector_properties, "tail", "input", "tail position:", expected_tail or "-")
self.check_vector_property(
vector_properties, "tail", "input", "tail position:", expected_tail or "",
field_disabled=input_fields_disabled
)
# Length
self.check_vector_property(vector_properties, "length", "input", "length:", expected_length or "-")
self.check_vector_property(
vector_properties, "length", "input", "length:", expected_length or "",
field_disabled=input_fields_disabled
)
# Angle
self.check_vector_property(vector_properties, "angle", "input", "angle:", expected_angle or "-")
self.check_vector_property(
vector_properties, "angle", "input", "angle:", expected_angle or "",
field_disabled=input_fields_disabled
)
# Slope
vector_slope = vector_properties.find_element_by_css_selector(".vector-prop-slope")
self.assertFalse(vector_slope.is_displayed())
......@@ -130,7 +143,8 @@ class TestVectorDraw(StudioEditableBaseTest):
)
def check_vector_property(
self, vector_properties, property_name, input_type, expected_label, expected_value=None
self, vector_properties, property_name, input_type, expected_label, expected_value=None,
field_disabled=False
):
vector_property = vector_properties.find_element_by_css_selector(
".vector-prop-{}".format(property_name)
......@@ -145,6 +159,8 @@ class TestVectorDraw(StudioEditableBaseTest):
)
if input_type == "input":
self.assertEquals(vector_property_input.get_attribute("value"), expected_value)
disabled = vector_property_input.get_attribute("disabled")
self.assertEquals(bool(disabled), field_disabled)
else:
selected_option = vector_property_input.find_element_by_css_selector('option[selected="selected"]')
self.assertEquals(selected_option.text, expected_value)
......@@ -297,7 +313,8 @@ class TestVectorDraw(StudioEditableBaseTest):
# "Vector Properties" should display correct info
self.check_vector_properties(
menu, is_present=True, expected_label="Custom properties label",
expected_name="N", expected_tail="2.00, 2.00", expected_length="4.00", expected_angle="45.00"
expected_name="N", expected_tail="2.00, 2.00", expected_length="4.00", expected_angle="45.00",
input_fields_disabled=False
)
self.check_edit_dropdown(menu, vectors)
......@@ -330,7 +347,8 @@ class TestVectorDraw(StudioEditableBaseTest):
# "Vector Properties" should display correct info
self.check_vector_properties(
menu, is_present=True, expected_label="Custom properties label",
expected_name="N", expected_tail="2.00, 2.00", expected_length="4.00", expected_angle="45.00"
expected_name="N", expected_tail="2.00, 2.00", expected_length="4.00", expected_angle="45.00",
input_fields_disabled=False
)
def reset(self, board, vectors, points):
......@@ -552,7 +570,8 @@ class TestVectorDraw(StudioEditableBaseTest):
menu = self.exercise.find_element_by_css_selector(".menu")
self.check_vector_properties(
menu, is_present=True, expected_label="Custom properties label",
expected_name="N", expected_tail="2.00, 2.00", expected_length="4.00", expected_angle="45.00"
expected_name="N", expected_tail="2.00, 2.00", expected_length="4.00", expected_angle="45.00",
input_fields_disabled=False
)
@data(
......
......@@ -123,7 +123,7 @@
}
.vectordraw_block .menu .vector-properties .vector-prop-list .row .vector-prop-update .update-error {
visibility: hidden;
display: none;
color: #ff0000;
}
......
......@@ -14,6 +14,10 @@
margin-bottom: 1em;
}
.vectordraw_edit_block #wysiwyg-description {
display: none;
}
.vectordraw_edit_block p {
margin-bottom: 1em;
font-size: 0.9em;
......@@ -59,6 +63,11 @@
float: right;
}
.vectordraw_block .menu .vector-properties .vector-prop-list .row .vector-prop-update .update-pending {
display: none;
color: #ffa500;
}
.vectordraw_edit_block h3 {
margin-top: 5px;
margin-bottom: 5px;
......@@ -83,11 +92,16 @@
}
.vectordraw_edit_block .checks .check span,
.vectordraw_edit_block .checks .check input[type="text"] {
.vectordraw_edit_block .checks .check input[type="number"] {
height: 1.5em;
min-width: 0px;
margin-right: 12px;
}
.vectordraw_edit_block .checks .check input[type="number"] {
padding: 0 0 0 5px;
}
.vectordraw_edit_block .checks .check input[type="checkbox"] {
height: 1.2em;
width: 20%;
......
......@@ -367,6 +367,10 @@ function VectorDrawXBlock(runtime, element, init_args) {
$('.vector-prop-slope input', this.element).val(slope.toFixed(2));
}
}
// Enable input fields
$('.vector-properties input').prop('disabled', false);
// Hide error message
$('.vector-prop-update .update-error', element).hide();
};
VectorDraw.prototype.resetVectorProperties = function(vector) {
......@@ -374,8 +378,8 @@ function VectorDrawXBlock(runtime, element, init_args) {
this.element.find('.menu .element-list-edit option').attr('selected', false);
// Select default value
$('.menu .element-list-edit option[value="-"]', element).attr('selected', true);
// Reset input fields to default values
$('.menu .vector-prop-list input', element).val('-');
// Reset input fields to default values and disable them
$('.menu .vector-prop-list input', element).prop('disabled', true).val('');
};
VectorDraw.prototype.isVectorTailDraggable = function(vector) {
......@@ -478,7 +482,7 @@ function VectorDrawXBlock(runtime, element, init_args) {
var values = [newTail[0], newTail[1], newLength, newAngle];
// Validate values
if (!_.some(values, Number.isNaN)) {
$('.vector-prop-update .update-error', element).css('visibility', 'hidden');
$('.vector-prop-update .update-error', element).hide();
// Use coordinates of new tail, new length, new angle to calculate new position of tip
var radians = newAngle * Math.PI / 180;
var newTip = [
......@@ -491,7 +495,7 @@ function VectorDrawXBlock(runtime, element, init_args) {
board_object.point2.setPosition(JXG.COORDS_BY_USER, newTip);
this.board.update();
} else {
$('.vector-prop-update .update-error', element).css('visibility', 'visible');
$('.vector-prop-update .update-error', element).show();
}
};
......
......@@ -4,11 +4,15 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
var VectorDraw = function(element_id, settings) {
this.board = null;
this.dragged_vector = null;
this.selectedVector = null;
this.drawMode = false;
this.wasUsed = false;
this.resultMode = false;
this.settings = settings;
this.numberOfVectors = this.settings.vectors.length;
this.checks = [
'tail', 'tail_x', 'tail_y', 'tip', 'tip_x', 'tip_y', 'coords', 'length', 'angle'
];
this.element = $('#' + element_id, element);
this.element.on('click', '.controls .add-vector', this.onAddVector.bind(this));
......@@ -28,17 +32,10 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
// (without making necessary adjustments in "Expected results" field)
// discard stale information about expected positions and checks
var vectorData = JSON.parse(fieldEditor.getContents('vectors')),
vectorNames = _.pluck(vectorData, 'name');
_.each(_.keys(this.settings.expected_result_positions), function(key) {
if (!_.contains(vectorNames, key)) {
delete this.settings.expected_result_positions[key];
}
}, this);
_.each(_.keys(this.settings.expected_result), function(key) {
if (!_.contains(vectorNames, key)) {
delete this.settings.expected_result[key];
}
}, this);
vectorNames = this.getVectorNames(vectorData);
var isStale = function(key) { return !_.contains(vectorNames, key); };
this.settings.expected_result_positions = _.omit(this.settings.expected_result_positions, isStale);
this.settings.expected_result = _.omit(this.settings.expected_result, isStale);
};
VectorDraw.prototype.render = function() {
......@@ -112,6 +109,13 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
this.board.create('point', coords, point.style);
};
VectorDraw.prototype.getVectorNames = function(vectorData) {
if (vectorData) {
return _.pluck(vectorData, 'name');
}
return _.pluck(this.settings.vectors, 'name');
};
VectorDraw.prototype.getVectorCoordinates = function(vec) {
var coords = vec.coords;
if (!coords) {
......@@ -232,26 +236,22 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
var boardObject = this.board.elementsByName[vectorName];
this.board.removeAncestors(boardObject);
// 2. Mark vector as "deleted" so it will be removed from "vectors" field on save
var vectorSettings = this.getVectorSettingsByName("" + vectorName);
var vectorSettings = this.getVectorSettingsByName(String(vectorName));
vectorSettings.deleted = true;
// 3. Remove entry that corresponds to selected vector from menu for selecting vector to edit
var idx = _.indexOf(this.settings.vectors, vectorSettings),
editOption = this.getEditMenuOption("vector", idx);
editOption.remove();
// 4. Discard information about expected position
var expectedPositions = this.settings.expected_result_positions;
if (expectedPositions[vectorName]) {
delete expectedPositions[vectorName];
this.settings.expected_result_positions = expectedPositions;
}
// 5. Discard information about expected result
var expectedResults = this.settings.expected_result;
if (expectedResults[vectorName]) {
delete expectedResults[vectorName];
this.settings.expected_result = expectedResults;
}
// 4. Discard information about expected position (if any)
delete this.settings.expected_result_positions[vectorName];
// 5. Discard information about expected result (if any)
delete this.settings.expected_result[vectorName];
// 6. Reset input fields for vector properties to default values
this.resetVectorProperties();
// 7. Reset selected vector
this.selectedVector = null;
// 8. Hide message about pending changes
$('.vector-prop-update .update-pending', element).hide();
};
VectorDraw.prototype.onEditResult = function(evt) {
......@@ -259,6 +259,9 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
this.resultMode = true;
// Save vector positions
this.settings.vectors = this.getState(); // Discards vectors that were removed from board
// Vector positions saved, so hide message about pending changes
this.selectedVector = null;
$('.vector-prop-update .update-pending', element).hide();
// Update vector positions using positions from expected result
var expectedResultPositions = this.settings.expected_result_positions;
if (!_.isEmpty(expectedResultPositions)) {
......@@ -286,13 +289,17 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
this.resetVectorProperties();
// Show controls for opting in and out of checks
$('.checks', element).show();
// Disable input fields that users should not be able to interact with unless a vector is selected
_.each(['tail', 'length', 'angle'], function(propName) {
$('.vector-prop-' + propName + ' input', element).prop('disabled', true);
});
};
VectorDraw.prototype.resetVectorProperties = function(vector) {
// Select default value
$('.menu .element-list-edit option[value="-"]', element).attr('selected', true);
// Reset input fields to default values
$('.menu .vector-prop-list input', element).val('-');
$('.menu .vector-prop-list input', element).val('');
};
VectorDraw.prototype.getMouseCoords = function(evt) {
......@@ -335,6 +342,12 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
if (angle < 0) {
angle += 360;
}
// If user selected different vector, hide message about pending changes
if (this.selectedVector && vector.name !== this.selectedVector.name) {
$('.vector-prop-update .update-pending', element).hide();
}
// Update selected vector
this.selectedVector = vector;
// Update menu for selecting vector to edit
this.element.find('.menu .element-list-edit option').attr('selected', false);
var idx = _.indexOf(this.settings.vectors, vec_settings),
......@@ -342,7 +355,7 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
editOption.attr('selected', true);
// Update properties
$('.vector-prop-name input', this.element).val(vector.name);
$('.vector-prop-label input', this.element).val(vec_settings.style.label || '-');
$('.vector-prop-label input', this.element).val(vec_settings.style.label || '');
$('.vector-prop-angle input', this.element).val(angle.toFixed(2));
if (vector.elType !== "line") {
var tailInput = x1.toFixed(2) + ", " + y1.toFixed(2);
......@@ -357,14 +370,13 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
else {
$('.vector-prop-length', this.element).hide();
}
// Enable input fields
$('.vector-properties input').prop('disabled', false);
};
VectorDraw.prototype.updateChecks = function(vector) {
var expectedResult = this.settings.expected_result[vector.name] || {};
var checks = [
'tail', 'tail_x', 'tail_y', 'tip', 'tip_x', 'tip_y', 'coords', 'length', 'angle'
];
_.each(checks, function(check) {
_.each(this.checks, function(check) {
var checkElement = $('#check-' + check, element);
// Update checkbox
if (expectedResult[check]) {
......@@ -375,10 +387,10 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
// Update tolerance
var tolerance = expectedResult[check + '_tolerance'];
if (tolerance) {
checkElement.find('input[type="text"]').val(tolerance.toFixed(1));
checkElement.find('input[type="number"]').val(tolerance.toFixed(1));
} else {
var defaultTolerance = check === 'angle' ? 2.0 : 1.0;
checkElement.find('input[type="text"]').val(defaultTolerance.toFixed(1));
checkElement.find('input[type="number"]').val(defaultTolerance.toFixed(1));
}
});
};
......@@ -400,16 +412,13 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
VectorDraw.prototype.saveChecks = function(vectorName) {
var expectedResult = {};
var checks = [
'tail', 'tail_x', 'tail_y', 'tip', 'tip_x', 'tip_y', 'coords', 'length', 'angle'
];
_.each(checks, function(check) {
_.each(this.checks, function(check) {
var checkElement = $('#check-' + check, element);
if (checkElement.find('input[type="checkbox"]').prop('checked')) {
// Insert (or update) check: Need current position of selected vector
expectedResult[check] = this.settings.expected_result_positions[vectorName][check];
// Insert (or update) tolerance
var tolerance = checkElement.find('input[type="text"]').val();
var tolerance = checkElement.find('input[type="number"]').val();
expectedResult[check + '_tolerance'] = parseFloat(tolerance);
}
}, this);
......@@ -457,7 +466,7 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
VectorDraw.prototype.getDefaultVector = function(coords) {
this.numberOfVectors += 1;
var name = "" + this.numberOfVectors,
var name = String(this.numberOfVectors),
description = "Vector " + name;
return {
name: name,
......@@ -504,7 +513,11 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
this.dragged_vector.point1.setProperty({fixed: false});
this.updateVectorProperties(this.dragged_vector);
if (this.resultMode) {
_.each(['name', 'label'], function(propName) {
$('.vector-prop-' + propName + ' input', element).prop('disabled', true);
});
this.updateChecks(this.dragged_vector);
$('.checks input', element).prop('disabled', false);
}
}
}
......@@ -536,7 +549,11 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
var vectorObject = this.board.elementsByName[vectorName];
this.updateVectorProperties(vectorObject);
if (this.resultMode) {
_.each(['name', 'label'], function(propName) {
$('.vector-prop-' + propName + ' input', element).prop('disabled', true);
});
this.updateChecks(vectorObject);
$('.checks input', element).prop('disabled', false);
}
};
......@@ -544,30 +561,32 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
if (!this.wasUsed) {
this.wasUsed = true;
}
// About to save changes, so hide message about pending changes
$('.vector-prop-update .update-pending', element).hide();
// Get name of vector that is currently "selected"
var vectorName = "" + $('.element-list-edit', element).find('option:selected').data('vector-name');
var vectorName = String($('.element-list-edit', element).find('option:selected').data('vector-name')),
editableProperties = ['name', 'label', 'tail', 'length', 'angle'],
newValues = {};
// Get values from input fields
var newName = $('.vector-prop-name input', element).val(),
newLabel = $('.vector-prop-label input', element).val(),
newTail = $('.vector-prop-tail input', element).val(),
newLength = $('.vector-prop-length input', element).val(),
newAngle = $('.vector-prop-angle input', element).val();
// Process values
newName = $.trim(newName);
newLabel = $.trim(newLabel);
newTail = _.map(newTail.split(/ *, */), function(coord) {
return parseFloat(coord);
_.each(editableProperties, function(prop) {
newValues[prop] = $.trim($('.vector-prop-' + prop + ' input', element).val());
});
newLength = parseFloat(newLength);
newAngle = parseFloat(newAngle);
// Process values
var newName = newValues.name,
newLabel = newValues.label,
newTail = _.map(newValues.tail.split(/ *, */), function(coord) { return parseFloat(coord); }),
newLength = parseFloat(newValues.length),
newAngle = parseFloat(newValues.angle);
// Validate and update values
var vectorSettings = this.getVectorSettingsByName(vectorName),
editOption = $('.menu .element-list-edit option[data-vector-name="' + vectorName + '"]', element),
var vectorNames = this.getVectorNames(),
vectorSettings = this.getVectorSettingsByName(vectorName),
boardObject = this.board.elementsByName[vectorName];
if (newName && newName !== vectorName) {
// 1. Update name
if (newName && newName !== vectorName && !_.contains(vectorNames, newName)) {
// Update vector settings
vectorSettings.name = newName;
// Update dropdown for selecting vector to edit
var editOption = $('.menu .element-list-edit option[data-vector-name="' + vectorName + '"]', element);
editOption.data('vector-name', newName);
editOption.text(newName);
// Update board
......@@ -589,14 +608,21 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
expectedResults[newName] = expectedResult;
delete expectedResults[vectorName];
}
} else {
$('.vector-prop-name input', element).val(vectorName);
}
if (newLabel && newLabel !== '-') {
// 2. Update label
if (newLabel) {
vectorSettings.style.label = newLabel;
boardObject.point2.name = newLabel; // Always prefer label for labeling vector on board
} else {
vectorSettings.style.label = null;
boardObject.point2.name = newName || vectorName; // ... but fall back on name if label was removed
}
// 3. Update tail, length, angle
var values = [newTail[0], newTail[1], newLength, newAngle];
if (!_.some(values, Number.isNaN)) {
$('.vector-prop-update .update-error', element).css('visibility', 'hidden');
$('.vector-prop-update .update-error', element).hide();
// Use coordinates of new tail, new length, new angle to calculate new position of tip
var radians = newAngle * Math.PI / 180;
var newTip = [
......@@ -616,7 +642,7 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
this.saveChecks(vectorName);
}
} else {
$('.vector-prop-update .update-error', element).css('visibility', 'visible');
$('.vector-prop-update .update-error', element).show();
}
};
......@@ -665,29 +691,30 @@ function VectorDrawXBlockEdit(runtime, element, init_args) {
// Set up click handlers
$('.save-button', element).on('click', function(e) {
e.preventDefault();
var data;
if (vectordraw.resultMode) { // Author edited both initial state and result
data = {
vectors: vectordraw.settings.vectors, // Corresponds to state vectors were in
// when author switched to result mode
expected_result_positions: vectordraw.settings.expected_result_positions,
expected_result: vectordraw.settings.expected_result
};
} else if (vectordraw.wasUsed) { // Author edited initial state
var state = vectordraw.getState();
data = {
vectors: state,
expected_result_positions: vectordraw.settings.expected_result_positions,
expected_result: vectordraw.settings.expected_result
};
} else { // Author did not use WYSIWYG editor
data = {};
var data = {};
if (vectordraw.wasUsed) {
// If author edited both initial state and result,
// vectordraw.settings.vectors corresponds to state vectors were in
// when author switched to result mode
data.vectors = vectordraw.resultMode ? vectordraw.settings.vectors : vectordraw.getState();
data.expected_result_positions = vectordraw.settings.expected_result_positions;
data.expected_result = vectordraw.settings.expected_result;
}
fieldEditor.save(data);
});
$('.cancel-button', element).on('click', function(e) {
e.preventDefault();
fieldEditor.cancel();
});
$('.info-button', element).on('click', function(e) {
e.preventDefault();
$('#wysiwyg-description', element).toggle();
});
$('input', element).on('change', function(e) {
$('.update-error').hide();
$('.update-pending').show();
});
}
......@@ -74,13 +74,13 @@
<span id="vector-prop-tail-label">
{% trans "tail position" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-tail-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-tail-label">
</div>
<div class="vector-prop vector-prop-length">
<span id="vector-prop-length-label">
{% trans "length" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-length-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-length-label">
</div>
</div>
<div class="row">
......@@ -88,13 +88,13 @@
<span id="vector-prop-angle-label">
{% trans "angle" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-angle-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-angle-label">
</div>
<div class="vector-prop vector-prop-slope">
<span id="vector-prop-slope-label">
{% trans "slope" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-slope-label" disabled="disabled">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-slope-label">
</div>
</div>
<div class="row">
......
......@@ -64,48 +64,81 @@
<li>
<!-- WYSIWYG editor -->
<div class="vectordraw_block vectordraw_edit_block">
<h2 aria-describedby="wysiwyg-description">WYSIWYG Editor</h2>
<h2 aria-describedby="wysiwyg-description">
WYSIWYG Editor
<button class="info-button" title="Info">
<span class="info-label fa fa-question" aria-hidden="true"></span>
<span class="sr">{% trans "Toggle information about how to use WYSIWYG editor" %}</span>
</button>
</h2>
<p id="wysiwyg-description">
{% blocktrans %}
Instead of using the "Vectors" and "Expected result" fields above
to define or modify the set of working vectors and expected result for this exercise,
you can also use the board below.
<div id="wysiwyg-description">
<p>
{% blocktrans %}
Instead of using the "Vectors" and "Expected result" fields above
to define or modify the set of working vectors and expected result for this exercise,
you can also use the board below.
{% endblocktrans %}
</p>
To add a vector, left-click the board where you want the vector to originate.
Keep holding down the left mouse button and drag your mouse pointer across the board
to achieve the desired length and angle for the vector.
Alternatively, you can click "Create vector", which will add a new vector
that starts at the center of the board and has a predefined length (3) and angle (90).
<p>
{% blocktrans %}
To add a vector, left-click the board where you want the vector to originate.
Keep holding down the left mouse button and drag your mouse pointer across the board
to achieve the desired length and angle for the vector.
Alternatively, you can click "Create vector", which will add a new vector
that starts at the center of the board and has a predefined length (3) and angle (90).
{% endblocktrans %}
</p>
To modify the position of an existing vector, left-click it, hold down the left mouse button,
and move your mouse pointer across the board. To modify length and/or angle,
left-click the tip of the vector and drag your mouse pointer across the board.
Alternatively, you can select an existing vector from the dropdown menu,
modify its tail position, length, and angle by changing the values
in the corresponding input fields, and click "Update" to update its position on the board.
You can also modify the name and label of a vector using this technique.
<p>
{% blocktrans %}
To modify the position of an existing vector, left-click it, hold down the left mouse button,
and move your mouse pointer across the board. To modify length and/or angle,
left-click the tip of the vector and drag your mouse pointer across the board.
Alternatively, you can select an existing vector from the dropdown menu,
modify its tail position, length, and angle by changing the values
in the corresponding input fields, and click "Update" to update its position on the board.
You can also modify the name and label of a vector using this technique.
{% endblocktrans %}
</p>
To remove an existing vector, left-click it or select it from the dropdown menu,
then click "Remove".
<p>
{% blocktrans %}
To remove an existing vector, left-click it or select it from the dropdown menu,
then click "Remove".
{% endblocktrans %}
</p>
When you are done defining the set of working vectors, click "Edit result"
to switch the editor to a mode that will allow you to define the expected result for this exercise.
In this mode you can operate on vectors as described above but you can not add or remove vectors,
and you may not change the name and label of a selected vector.
<p>
{% blocktrans %}
When you are done defining the set of working vectors, click "Edit result"
to switch the editor to a mode that will allow you to define the expected result for this exercise.
In this mode you can operate on vectors as described above but you can not add or remove vectors,
and you may not change the name and label of a selected vector.
{% endblocktrans %}
</p>
To define the expected result for the exercise, place each vector where it would be located
in a correct solution. When a vector is selected, use the menu to the right of the board
to select the checks that you would like the grader to perform for this vector,
and click "Update". Note that if you do not select any checks for a given vector,
no checks at all will be performed for it during grading (i.e., the grader will skip a presence check).
<p>
{% blocktrans %}
To define the expected result for the exercise, place each vector where it would be located
in a correct solution. When a vector is selected and positioned correctly,
use the menu to the right of the board to select the checks that you would like the grader
to perform for this vector, then click "Update" to save expected position and associated checks
for the vector. Note that if you do not select any checks for a given vector,
no checks at all will be performed for it during grading (i.e., the grader will skip a presence check).
{% endblocktrans %}
</p>
Finally, note that if you make changes using the board below, any changes you made
via the "Vectors" and "Expected results" fields above will be overwritten
when you save the settings for this exercise by clicking the "Save" button
at the bottom of this dialog.
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
Finally, note that if you make changes using the board below, any changes you made
via the "Vectors" and "Expected results" fields above will be overwritten
when you save the settings for this exercise by clicking the "Save" button
at the bottom of this dialog.
{% endblocktrans %}
</p>
</div>
<div id="vectordraw">
<div class="menu" style="width: {{ self.width }}px;">
......@@ -134,7 +167,7 @@
<span id="vector-prop-name-label">
{% trans "name" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-name-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-name-label">
</div>
</div>
<div class="row">
......@@ -142,13 +175,13 @@
<span id="vector-prop-label-label">
{% trans "label" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-label-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-label-label">
</div>
<div class="vector-prop vector-prop-tail">
<span id="vector-prop-tail-label">
{% trans "tail position" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-tail-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-tail-label">
</div>
</div>
<div class="row">
......@@ -156,13 +189,13 @@
<span id="vector-prop-length-label">
{% trans "length" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-length-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-length-label">
</div>
<div class="vector-prop vector-prop-angle">
<span id="vector-prop-angle-label">
{% trans "angle" %}:
</span>
<input type="text" value="-" aria-labelledby="vector-prop-angle-label">
<input type="text" disabled="disabled" placeholder="-" aria-labelledby="vector-prop-angle-label">
</div>
</div>
<div class="row">
......@@ -171,6 +204,9 @@
<span class="update-label" aria-hidden="true">{% trans "Update" %}</span>
<span class="sr">{% trans "Update properties of selected element" %}</span>
</button>
<span class="update-pending">
{% trans "Pending changes." %}
</span>
<span class="update-error">{% trans "Invalid input." %}</span>
</div>
<div class="vector-prop vector-remove">
......@@ -194,13 +230,13 @@
<span id="tail-check-label">
{% trans "check tail" %}:
</span>
<input type="checkbox" aria-labelledby="tail-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="tail-check-label">
</div>
<div class="row">
<span id="tail-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="tail-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="tail-tolerance-label">
</div>
</div>
<div class="check" id="check-tip">
......@@ -208,13 +244,13 @@
<span id="tip-check-label">
{% trans "check tip" %}:
</span>
<input type="checkbox" aria-labelledby="tip-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="tip-check-label">
</div>
<div class="row">
<span id="tip-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="tip-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="tip-tolerance-label">
</div>
</div>
<div class="check" id="check-tail_x">
......@@ -222,13 +258,13 @@
<span id="tail-x-check-label">
{% trans "check tail(x)" %}:
</span>
<input type="checkbox" aria-labelledby="tail-x-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="tail-x-check-label">
</div>
<div class="row">
<span id="tail-x-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="tail-x-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="tail-x-tolerance-label">
</div>
</div>
<div class="check" id="check-tail_y">
......@@ -236,13 +272,13 @@
<span id="tail-y-check-label">
{% trans "check tail(y)" %}:
</span>
<input type="checkbox" aria-labelledby="tail-y-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="tail-y-check-label">
</div>
<div class="row">
<span id="tail-y-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="tail-y-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="tail-y-tolerance-label">
</div>
</div>
<div class="check" id="check-tip_x">
......@@ -250,13 +286,13 @@
<span id="tip-x-check-label">
{% trans "check tip(x)" %}:
</span>
<input type="checkbox" aria-labelledby="tip-x-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="tip-x-check-label">
</div>
<div class="row">
<span id="tip-x-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="tip-x-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="tip-x-tolerance-label">
</div>
</div>
<div class="check" id="check-tip_y">
......@@ -264,13 +300,13 @@
<span id="tip-y-check-label">
{% trans "check tip(y)" %}:
</span>
<input type="checkbox" aria-labelledby="tip-y-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="tip-y-check-label">
</div>
<div class="row">
<span id="tip-y-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="tip-y-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="tip-y-tolerance-label">
</div>
</div>
<div class="check" id="check-coords">
......@@ -278,13 +314,13 @@
<span id="coords-check-label">
{% trans "check coords" %}:
</span>
<input type="checkbox" aria-labelledby="coords-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="coords-check-label">
</div>
<div class="row">
<span id="coords-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="coords-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="coords-tolerance-label">
</div>
</div>
<div class="check" id="check-length">
......@@ -292,13 +328,13 @@
<span id="length-check-label">
{% trans "check length" %}:
</span>
<input type="checkbox" aria-labelledby="length-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="length-check-label">
</div>
<div class="row">
<span id="length-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="1.0" aria-labelledby="length-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="length-tolerance-label">
</div>
</div>
<div class="check" id="check-angle">
......@@ -306,13 +342,13 @@
<span id="angle-check-label">
{% trans "check angle" %}:
</span>
<input type="checkbox" aria-labelledby="angle-check-label">
<input type="checkbox" disabled="disabled" aria-labelledby="angle-check-label">
</div>
<div class="row">
<span id="angle-tolerance-label">
{% trans "tolerance" %}:
</span>
<input type="text" value="2.0" aria-labelledby="angle-tolerance-label">
<input type="number" disabled="disabled" min="0" step="0.1" placeholder="-" aria-labelledby="angle-tolerance-label">
</div>
</div>
</div>
......
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