Commit a14e6f0a by Usman Khalid Committed by muzaffaryousaf

Accessibility tweaks for account settings and profile pages.

TNL-1660
parent 7babb3ef
...@@ -161,7 +161,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -161,7 +161,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
validValue: 'My Name', validValue: 'My Name',
invalidValue1: '', invalidValue1: '',
invalidValue2: '@', invalidValue2: '@',
validationError: "Think again!" validationError: "Think again!",
defaultValue: ''
}, requests); }, requests);
} }
...@@ -180,7 +181,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -180,7 +181,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
validValue: Helpers.FIELD_OPTIONS[1][0], validValue: Helpers.FIELD_OPTIONS[1][0],
invalidValue1: Helpers.FIELD_OPTIONS[2][0], invalidValue1: Helpers.FIELD_OPTIONS[2][0],
invalidValue2: Helpers.FIELD_OPTIONS[3][0], invalidValue2: Helpers.FIELD_OPTIONS[3][0],
validationError: "Nope, this will not do!" validationError: "Nope, this will not do!",
defaultValue: null
}, requests); }, requests);
}); });
......
...@@ -15,12 +15,12 @@ define(['underscore'], function(_) { ...@@ -15,12 +15,12 @@ define(['underscore'], function(_) {
username: 'student', username: 'student',
name: 'Student', name: 'Student',
email: 'student@edx.org', email: 'student@edx.org',
level_of_education: '', level_of_education: null,
gender: '', gender: null,
year_of_birth: '3', // Note: test birth year range is a string from 0-3 year_of_birth: '3', // Note: test birth year range is a string from 0-3
requires_parental_consent: false, requires_parental_consent: false,
country: '', country: '1',
language: '', language: null,
bio: "About the student", bio: "About the student",
language_proficiencies: [{code: '1'}], language_proficiencies: [{code: '1'}],
profile_image: PROFILE_IMAGE profile_image: PROFILE_IMAGE
......
...@@ -114,7 +114,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -114,7 +114,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
expectMessageContains(view, view.helpMessage); expectMessageContains(view, view.helpMessage);
view.showSuccessMessage(); view.showSuccessMessage();
expectMessageContains(view, view.indicators.success); expectMessageContains(view, view.indicators.success);
jasmine.Clock.tick(5000); jasmine.Clock.tick(7000);
// Message gets reset // Message gets reset
expectMessageContains(view, view.helpMessage); expectMessageContains(view, view.helpMessage);
...@@ -122,7 +122,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -122,7 +122,7 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
expectMessageContains(view, view.indicators.success); expectMessageContains(view, view.indicators.success);
// But if we change the message, it should not get reset. // But if we change the message, it should not get reset.
view.showHelpMessage("Do not reset this!"); view.showHelpMessage("Do not reset this!");
jasmine.Clock.tick(5000); jasmine.Clock.tick(7000);
expectMessageContains(view, "Do not reset this!"); expectMessageContains(view, "Do not reset this!");
}; };
...@@ -138,9 +138,11 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -138,9 +138,11 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
} else { } else {
expectTitleAndMessageToContain(view, data.title, data.helpMessage, false); expectTitleAndMessageToContain(view, data.title, data.helpMessage, false);
} }
expect(view.el).toHaveClass('mode-edit'); expect(view.el).toHaveClass('mode-edit');
expect(view.fieldValue()).not.toContain(data.validValue);
if (view.fieldValue() !== null) {
expect(view.fieldValue()).not.toContain(data.validValue);
}
view.$(data.valueInputSelector).val(data.validValue).change(); view.$(data.valueInputSelector).val(data.validValue).change();
// When the value in the field is changed // When the value in the field is changed
...@@ -185,8 +187,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -185,8 +187,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
view.$(data.valueInputSelector).val('').change(); view.$(data.valueInputSelector).val('').change();
// When the value in the field is changed // When the value in the field is changed
expect(view.fieldValue()).toBe(''); expect(view.fieldValue()).toBe(data.defaultValue);
request_data[data.valueAttribute] = ''; request_data[data.valueAttribute] = data.defaultValue;
AjaxHelpers.expectJsonRequest( AjaxHelpers.expectJsonRequest(
requests, 'PATCH', url, request_data requests, 'PATCH', url, request_data
); );
......
...@@ -121,7 +121,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -121,7 +121,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
validValue: 'My Name', validValue: 'My Name',
invalidValue1: 'Your Name', invalidValue1: 'Your Name',
invalidValue2: 'Her Name', invalidValue2: 'Her Name',
validationError: "Think again!" validationError: "Think again!",
defaultValue: ''
}, requests); }, requests);
}); });
...@@ -164,7 +165,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -164,7 +165,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
validValue: FieldViewsSpecHelpers.SELECT_OPTIONS[0][0], validValue: FieldViewsSpecHelpers.SELECT_OPTIONS[0][0],
invalidValue1: FieldViewsSpecHelpers.SELECT_OPTIONS[1][0], invalidValue1: FieldViewsSpecHelpers.SELECT_OPTIONS[1][0],
invalidValue2: FieldViewsSpecHelpers.SELECT_OPTIONS[2][0], invalidValue2: FieldViewsSpecHelpers.SELECT_OPTIONS[2][0],
validationError: "Nope, this will not do!" validationError: "Nope, this will not do!",
defaultValue: null
}, requests); }, requests);
}); });
...@@ -188,7 +190,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j ...@@ -188,7 +190,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
validValue: FieldViewsSpecHelpers.SELECT_OPTIONS[0][0], validValue: FieldViewsSpecHelpers.SELECT_OPTIONS[0][0],
invalidValue1: FieldViewsSpecHelpers.SELECT_OPTIONS[1][0], invalidValue1: FieldViewsSpecHelpers.SELECT_OPTIONS[1][0],
invalidValue2: FieldViewsSpecHelpers.SELECT_OPTIONS[2][0], invalidValue2: FieldViewsSpecHelpers.SELECT_OPTIONS[2][0],
validationError: "Nope, this will not do!" validationError: "Nope, this will not do!",
defaultValue: null
}, requests); }, requests);
}); });
......
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
if (_.isArray(modelValue) && modelValue.length > 0) { if (_.isArray(modelValue) && modelValue.length > 0) {
return modelValue[0].code; return modelValue[0].code;
} else { } else {
return ''; return null;
} }
}, },
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
var usernameFieldView = new FieldsView.ReadonlyFieldView({ var usernameFieldView = new FieldsView.ReadonlyFieldView({
model: accountSettingsModel, model: accountSettingsModel,
screenReaderTitle: gettext('Username'),
valueAttribute: "username", valueAttribute: "username",
helpMessage: "" helpMessage: ""
}); });
...@@ -70,12 +71,12 @@ ...@@ -70,12 +71,12 @@
var sectionOneFieldViews = [ var sectionOneFieldViews = [
new FieldsView.DropdownFieldView({ new FieldsView.DropdownFieldView({
model: accountSettingsModel, model: accountSettingsModel,
screenReaderTitle: gettext('Location'), screenReaderTitle: gettext('Country'),
required: true, required: true,
editable: editable, editable: editable,
showMessages: false, showMessages: false,
iconName: 'fa-map-marker', iconName: 'fa-map-marker',
placeholderValue: '', placeholderValue: gettext('Add Country'),
valueAttribute: "country", valueAttribute: "country",
options: options.country_options, options: options.country_options,
helpMessage: '' helpMessage: ''
......
...@@ -59,7 +59,10 @@ ...@@ -59,7 +59,10 @@
// Update model to get the latest urls of profile image. // Update model to get the latest urls of profile image.
this.model.fetch().done(function () { this.model.fetch().done(function () {
view.setCurrentStatus(''); view.setCurrentStatus('');
view.render();
view.$('.u-field-upload-button').focus();
}).fail(function () { }).fail(function () {
view.setCurrentStatus('');
view.showErrorMessage(view.errorMessage); view.showErrorMessage(view.errorMessage);
}); });
}, },
...@@ -67,7 +70,6 @@ ...@@ -67,7 +70,6 @@
imageChangeFailed: function (e, data) { imageChangeFailed: function (e, data) {
this.setCurrentStatus(''); this.setCurrentStatus('');
this.showImageChangeFailedMessage(data.jqXHR.status, data.jqXHR.responseText); this.showImageChangeFailedMessage(data.jqXHR.status, data.jqXHR.responseText);
this.render();
}, },
showImageChangeFailedMessage: function (status, responseText) { showImageChangeFailedMessage: function (status, responseText) {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
var Mustache = window.Mustache || RequireMustache; var Mustache = window.Mustache || RequireMustache;
var messageRevertDelay = 4000; var messageRevertDelay = 6000;
var FieldViews = {}; var FieldViews = {};
FieldViews.FieldView = Backbone.View.extend({ FieldViews.FieldView = Backbone.View.extend({
...@@ -176,10 +176,7 @@ ...@@ -176,10 +176,7 @@
this.showSuccessMessage(); this.showSuccessMessage();
}, },
showDisplayMode: function(render) { updateDisplayModeClass: function() {
this.mode = 'display';
if (render) { this.render(); }
this.$el.removeClass('mode-edit'); this.$el.removeClass('mode-edit');
this.$el.toggleClass('mode-hidden', (this.editable === 'never' && !this.modelValueIsSet())); this.$el.toggleClass('mode-hidden', (this.editable === 'never' && !this.modelValueIsSet()));
...@@ -187,6 +184,12 @@ ...@@ -187,6 +184,12 @@
this.$el.toggleClass('mode-display', (this.modelValueIsSet())); this.$el.toggleClass('mode-display', (this.modelValueIsSet()));
}, },
showDisplayMode: function(render) {
this.mode = 'display';
if (render) { this.render(); }
this.updateDisplayModeClass();
},
showEditMode: function(render) { showEditMode: function(render) {
this.mode = 'edit'; this.mode = 'edit';
if (render) { this.render(); } if (render) { this.render(); }
...@@ -233,6 +236,7 @@ ...@@ -233,6 +236,7 @@
this.$el.html(this.template({ this.$el.html(this.template({
id: this.options.valueAttribute, id: this.options.valueAttribute,
title: this.options.title, title: this.options.title,
screenReaderTitle: this.options.screenReaderTitle || this.options.title,
value: this.modelValue(), value: this.modelValue(),
message: this.helpMessage message: this.helpMessage
})); }));
...@@ -345,7 +349,8 @@ ...@@ -345,7 +349,8 @@
}, },
fieldValue: function () { fieldValue: function () {
return this.$('.u-field-value select').val(); var value = this.$('.u-field-value select').val();
return value === '' ? null : value;
}, },
displayValue: function (value) { displayValue: function (value) {
...@@ -358,16 +363,17 @@ ...@@ -358,16 +363,17 @@
}, },
updateValueInField: function () { updateValueInField: function () {
this.$('.u-field-value select').val(this.modelValue() || '');
var value = this.displayValue(this.modelValue() || '');
if (this.modelValueIsSet() === false) {
value = this.options.placeholderValue || '';
}
this.$('.u-field-value').attr('aria-label', this.options.title);
this.$('.u-field-value-readonly').html(Mustache.escapeHtml(value));
if (this.mode === 'display') { if (this.mode === 'display') {
var value = this.displayValue(this.modelValue() || ''); this.updateDisplayModeClass();
if (this.modelValueIsSet() === false) {
value = this.options.placeholderValue || '';
}
this.$('.u-field-value').attr('aria-label', this.options.title);
this.$('.u-field-value-readonly').html(Mustache.escapeHtml(value));
this.showDisplayMode(false);
} else {
this.$('.u-field-value select').val(this.modelValue() || '');
} }
}, },
...@@ -377,6 +383,13 @@ ...@@ -377,6 +383,13 @@
this.saveAttributes(attributes); this.saveAttributes(attributes);
}, },
showDisplayMode: function(render) {
this._super(render);
if (this.editable === 'toggle') {
this.$('.u-field-value a').focus();
}
},
showEditMode: function(render) { showEditMode: function(render) {
this._super(render); this._super(render);
if (this.editable === 'toggle') { if (this.editable === 'toggle') {
...@@ -386,10 +399,13 @@ ...@@ -386,10 +399,13 @@
saveSucceeded: function() { saveSucceeded: function() {
if (this.editable === 'toggle') { if (this.editable === 'toggle') {
this.showDisplayMode(true); this.showDisplayMode();
} else { }
this.showEditMode(true);
if (this.options.required && this.modelValueIsSet()) {
this.$('option[value=""]').remove();
} }
this._super(); this._super();
}, },
...@@ -410,13 +426,13 @@ ...@@ -410,13 +426,13 @@
'focusout textarea': 'finishEditing', 'focusout textarea': 'finishEditing',
'change textarea': 'adjustTextareaHeight', 'change textarea': 'adjustTextareaHeight',
'keyup textarea': 'adjustTextareaHeight', 'keyup textarea': 'adjustTextareaHeight',
'keydown textarea': 'adjustTextareaHeight', 'keydown textarea': 'onKeyDown',
'paste textarea': 'adjustTextareaHeight', 'paste textarea': 'adjustTextareaHeight',
'cut textarea': 'adjustTextareaHeight' 'cut textarea': 'adjustTextareaHeight'
}, },
initialize: function (options) { initialize: function (options) {
_.bindAll(this, 'render', 'adjustTextareaHeight', 'fieldValue', 'saveValue', 'updateView'); _.bindAll(this, 'render', 'onKeyDown', 'adjustTextareaHeight', 'fieldValue', 'saveValue', 'updateView');
this._super(options); this._super(options);
this.listenTo(this.model, "change:" + this.options.valueAttribute, this.updateView); this.listenTo(this.model, "change:" + this.options.valueAttribute, this.updateView);
}, },
...@@ -443,6 +459,15 @@ ...@@ -443,6 +459,15 @@
return this; return this;
}, },
onKeyDown: function (event) {
if (event.keyCode === 13) {
event.preventDefault();
this.finishEditing(event);
} else {
this.adjustTextareaHeight();
}
},
adjustTextareaHeight: function() { adjustTextareaHeight: function() {
var textarea = this.$('textarea'); var textarea = this.$('textarea');
textarea.css('height', 'auto').css('height', textarea.prop('scrollHeight') + 10); textarea.css('height', 'auto').css('height', textarea.prop('scrollHeight') + 10);
...@@ -483,6 +508,7 @@ ...@@ -483,6 +508,7 @@
this._super(); this._super();
if (this.editable === 'toggle') { if (this.editable === 'toggle') {
this.showDisplayMode(true); this.showDisplayMode(true);
this.$('a').focus();
} }
} }
}); });
...@@ -552,7 +578,6 @@ ...@@ -552,7 +578,6 @@
this._super(options); this._super(options);
_.bindAll(this, 'render', 'imageChangeSucceeded', 'imageChangeFailed', 'fileSelected', _.bindAll(this, 'render', 'imageChangeSucceeded', 'imageChangeFailed', 'fileSelected',
'watchForPageUnload', 'onBeforeUnload'); 'watchForPageUnload', 'onBeforeUnload');
this.listenTo(this.model, "change:" + this.options.valueAttribute, this.render);
}, },
render: function () { render: function () {
......
...@@ -121,3 +121,13 @@ ...@@ -121,3 +121,13 @@
color: $gray-l1; color: $gray-l1;
} }
} }
.u-field-dropdown {
&.mode-display select, &.mode-placeholder select {
display: none;
}
&.mode-edit a.u-field-value-display {
display: none;
}
}
...@@ -5,26 +5,23 @@ ...@@ -5,26 +5,23 @@
<% } %> <% } %>
<% if (iconName) { %> <% if (iconName) { %>
<i class="u-field-icon icon fa <%- iconName %> fa-fw" aria-hidden="true" ></i> <i class="u-field-icon icon fa <%- iconName %> fa-fw" aria-hidden="true"></i>
<% } %> <% } %>
<span class="u-field-value"> <span class="u-field-value">
<% if (mode === 'edit') { %> <select name="select" id="u-field-select-<%- id %>" aria-describedby="u-field-message-<%- id %>">
<select name="select" id="u-field-select-<%- id %>" aria-describedby="u-field-message-<%- id %>"> <% if (showBlankOption) { %>
<% if (showBlankOption) { %> <option value=""></option>
<option value=""></option> <% } %>
<% } %> <% _.each(selectOptions, function(selectOption) { %>
<% _.each(selectOptions, function(selectOption) { %> <option value="<%- selectOption[0] %>"><%- selectOption[1] %></option>
<option value="<%- selectOption[0] %>"><%- selectOption[1] %></option> <% }); %>
<% }); %> </select>
</select> <a href="#" class="u-field-value-display">
<% } else { %> <span class="sr"><%- screenReaderTitle %></span>
<a href="#" class="u-field-value-display"> <span class="u-field-value-readonly"></span>
<span class="sr"><%- screenReaderTitle %></span> <span class="sr"><%- gettext('Click to edit') %></span>
<span class="u-field-value-readonly"></span> </a>
<span class="sr"><%- gettext('Click to edit') %></span>
</a>
<% }%>
</span> </span>
<span class="u-field-message" id="u-field-message-<%- id %>"> <span class="u-field-message" id="u-field-message-<%- id %>">
......
<label class="u-field-title" for="u-field-input-<%- id %>"> <label class="u-field-title" aria-hidden="true">
<%- gettext(title) %> <%- title %>
</label> </label>
<span class="sr" for="u-field-input-<%- id %>"><%- screenReaderTitle %></span>
<span class="u-field-value"> <span class="u-field-value">
<input id="u-field-input-<%- id %>" aria-describedby="u-field-message-<%- id %>" type="text" name="input" readonly=true value="<%- value %>"> <input id="u-field-input-<%- id %>" aria-describedby="u-field-message-<%- id %>" type="text" name="input" readonly=true value="<%- value %>">
</span> </span>
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
if (mode === 'edit') { if (mode === 'edit') {
%><textarea id="u-field-textarea-<%- id %>" rows="4" aria-describedby="u-field-placeholder-value-<%- id %>"><%- value %></textarea><% %><textarea id="u-field-textarea-<%- id %>" rows="4" aria-describedby="u-field-placeholder-value-<%- id %>"><%- value %></textarea><%
} else { } else {
%><a href="#" class="u-field-value-display"><span class="sr"><%- screenReaderTitle %></span><span class="u-field-value-readonly" aria-hidden="false" aria-describedby="u-field-placeholder-value-<%- id %>"><%- value %></span><span class="sr"><%- gettext('Click to edit') %></span></a><% %><a href="#"><span class="sr"><%- screenReaderTitle %></span><span class="u-field-value-readonly" aria-hidden="false" aria-describedby="u-field-placeholder-value-<%- id %>"><%- value %></span><span class="sr"><%- gettext('Click to edit') %></span></a><%
} }
%><span class="sr" id="u-field-placeholder-value-<%- id %>"><%- placeholderValue %></span> %><span class="sr" id="u-field-placeholder-value-<%- id %>"><%- placeholderValue %></span>
</div> </div>
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
<%block name="pagetitle">${_("Account Settings")}</%block> <%block name="pagetitle">${_("Account Settings")}</%block>
<%block name="nav_skip">#u-field-input-username</%block>
<%block name="header_extras"> <%block name="header_extras">
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
<%block name="pagetitle">${_("Learner Profile")}</%block> <%block name="pagetitle">${_("Learner Profile")}</%block>
<%block name="nav_skip">#u-field-select-account_privacy</%block>
<%block name="bodyclass">view-profile</%block> <%block name="bodyclass">view-profile</%block>
......
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