Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Bug 1068700 - improved accessibility of email list bottom toolbar. #27782

Merged
merged 1 commit into from Jan 30, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions apps/email/js/cards/message_list.html
Expand Up @@ -125,12 +125,15 @@ <h1 data-prop="headerNode" class="msg-listedit-header-label">
<div class="msg-activity-infobar hidden">
</div>
<!-- Toolbar for non-multi-edit state -->
<ul data-prop="normalToolbar" class="bb-tablist msg-list-action-toolbar">
<ul data-prop="normalToolbar" class="bb-tablist msg-list-action-toolbar"
role="toolbar">
<li role="presentation" class="msg-nonsearch-only">
<button data-prop="refreshBtn" data-event="click:onRefresh"
class="icon msg-refresh-btn" data-state="synchronized"></button>
class="icon msg-refresh-btn" data-state="synchronized"
data-l10n-id="messages-refresh-button">
</button>
</li>
<li role="presentation" class="msg-nonsearch-only msg-last-sync">
<li role="status" class="msg-nonsearch-only msg-last-sync">
<span data-prop="lastSyncedLabel"
class="msg-last-synced-label"
data-l10n-id="folder-last-synced-label"></span>
Expand All @@ -139,7 +142,7 @@ <h1 data-prop="headerNode" class="msg-listedit-header-label">
</li>
<li role="presentation">
<button data-prop="editBtn" data-event="click:setEditModeStart"
class="icon msg-edit-btn"></button>
class="icon msg-edit-btn" data-l10n-id="edit-button"></button>
</li>
</ul>

Expand Down
23 changes: 18 additions & 5 deletions apps/email/js/cards/message_list.js
Expand Up @@ -761,6 +761,21 @@ return [
headerCursor.messagesSlice.requestGrowth(1, true);
},

/**
* Set the refresh button state based on the new message status.
*/
setRefreshState: function(syncing) {
if (syncing) {
this.refreshBtn.dataset.state = 'synchronizing';
this.refreshBtn.setAttribute('role', 'progressbar');
mozL10n.setAttributes(this.refreshBtn, 'messages-refresh-progress');
} else {
this.refreshBtn.dataset.state = 'synchronized';
this.refreshBtn.removeAttribute('role');
mozL10n.setAttributes(this.refreshBtn, 'messages-refresh-button');
}
},

// The funny name because it is auto-bound as a listener for
// messagesSlice events in headerCursor using a naming convention.
messages_status: function(newStatus) {
Expand All @@ -782,8 +797,7 @@ return [
this.syncingNode.classList.remove('collapsed');
this.syncMoreNode.classList.add('collapsed');
this.hideEmptyLayout();

this.refreshBtn.dataset.state = 'synchronizing';
this.setRefreshState(true);
} else if (newStatus === 'syncfailed' ||
newStatus === 'synced') {
if (newStatus === 'syncfailed') {
Expand All @@ -795,7 +809,7 @@ return [
text: mozL10n.get('toaster-retryable-syncfailed')
});
}
this.refreshBtn.dataset.state = 'synchronized';
this.setRefreshState(false);
this.syncingNode.classList.add('collapsed');
this._manuallyTriggeredSync = false;
}
Expand Down Expand Up @@ -1752,12 +1766,10 @@ return [
}

this.editBtn.disabled = true;
this.refreshBtn.dataset.state = 'synchronizing';
} else {
// After sync, the edit button should remain disabled only if
// the list is empty.
this.editBtn.disabled = this.isEmpty();
this.refreshBtn.dataset.state = 'synchronized';

// Similarly, we must stop the refresh icons for each message
// from rotating further. For instance, if we are offline, we
Expand All @@ -1767,6 +1779,7 @@ return [
items[i].classList.remove('msg-header-syncing-section-syncing');
}
}
this.setRefreshState(syncing);
},

onRefresh: function() {
Expand Down
15 changes: 15 additions & 0 deletions apps/email/locales/email.en-US.properties
Expand Up @@ -660,6 +660,21 @@ drawer-settings-link=Settings
# font size to fit longer text.
folder-last-synced-label=Last sync:

# LOCALIZATION NOTE(messages-refresh-button): For the message-list, a label for
# a button that refreshes the list of messages in the folder. The following
# string is spoken by screen readers and not shown on the screen.
messages-refresh-button.ariaLabel=Refresh
# LOCALIZATION NOTE(messages-refresh-progress): For the message-list, a label
# for a button that refreshes the list of messages in the folder when the sync
# is in progress. It is only visible when reshing is in progress. The following
# string is spoken by screen readers and not shown on the screen.
messages-refresh-progress.ariaValueText=Refreshing

# LOCALIZATION NOTE(edit-button): For the message-list, a label for a button
# that activates edit mode for the message list. The following string is spoken
# by screen readers and not shown on the screen.
edit-button.ariaLabel=Edit

# LOCALIZATION NOTE(message-list-top-action):
# In the message-list, as the user scrolls down, an action bar will scroll into
# view that if tapped will take the user to the top of the screen. That bar
Expand Down
75 changes: 75 additions & 0 deletions apps/email/test/unit/messsage_list_card_test.js
@@ -0,0 +1,75 @@
'use strict';
/*global requireApp, suite, setup, testConfig, test, assert, suiteSetup,
suiteTeardown */

requireApp('email/js/alameda.js');
requireApp('email/test/config.js');

suite('message_list', function() {
var subject, MessageList;
var mockMessagesSlice = { items: [] };

function testRefreshBtnAccessibility(syncing) {
assert.equal(subject.refreshBtn.getAttribute('data-l10n-id'),
syncing ? 'messages-refresh-progress' : 'messages-refresh-button');
if (syncing) {
assert.equal(subject.refreshBtn.getAttribute('role'), 'progressbar');
} else {
assert.isNull(subject.refreshBtn.getAttribute('role'));
}
}

suiteSetup(function(done) {
testConfig({
suiteTeardown: suiteTeardown,
done: done
}, ['header_cursor', 'element!cards/message_list'], function(hc, ml) {
hc.cursor.messagesSlice = mockMessagesSlice;
MessageList = ml;
});
});

setup(function() {
subject = new MessageList();
});

suite('messages_status', function() {
setup(function() {
subject.curFolder = { type: 'inbox' };
});

test('synchronizing', function() {
testRefreshBtnAccessibility(false);
subject.messages_status('synchronizing');
testRefreshBtnAccessibility(true);
});

test('synced', function() {
testRefreshBtnAccessibility(false);
subject.messages_status('synced');
testRefreshBtnAccessibility(false);
});
});

suite('toggleOutboxSyncingDisplay', function() {
setup(function() {
subject.curFolder = { type: 'outbox' };
});

test('syncing', function() {
testRefreshBtnAccessibility(false);
subject.toggleOutboxSyncingDisplay(true);
testRefreshBtnAccessibility(true);
});

test('not syncing', function() {
setup(function() {
subject._outboxSyncing = true;
});

testRefreshBtnAccessibility(false);
subject.toggleOutboxSyncingDisplay(false);
testRefreshBtnAccessibility(false);
});
});
});