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

Commit

Permalink
Bug 1069593 - making usage graph accessible.
Browse files Browse the repository at this point in the history
  • Loading branch information
yzen authored and rvandermeulen committed Feb 21, 2015
1 parent db973fb commit 56a0369
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 19 deletions.
16 changes: 8 additions & 8 deletions apps/costcontrol/elements/appdetail-view.html
Expand Up @@ -6,14 +6,14 @@ <h1>{{localized-app-name}}</h1>

<div class="view-scroll">
<section class="usage fade">
<section id="app-graphic-area" class="graph">
<canvas id="app-background-layer"></canvas>
<canvas id="app-wifi-layer" hidden></canvas>
<canvas id="app-mobile-layer"></canvas>
<canvas id="app-axis-layer"></canvas>
<canvas id="app-today-layer"></canvas>
<canvas id="app-warning-layer"></canvas>
<canvas id="app-limits-layer"></canvas>
<section id="app-graphic-area" class="graph" role="img" aria-labelledby="app-axis-layer app-today-layer app-limits-layer app-warning-layer">
<canvas id="app-background-layer" aria-hidden="true"></canvas>
<canvas id="app-wifi-layer" hidden aria-hidden="true"></canvas>
<canvas id="app-mobile-layer" aria-hidden="true"></canvas>
<canvas id="app-axis-layer" aria-hidden="true"></canvas>
<canvas id="app-today-layer" aria-hidden="true"></canvas>
<canvas id="app-warning-layer" aria-hidden="true"></canvas>
<canvas id="app-limits-layer" aria-hidden="true"></canvas>
<img hidden alt="" src="./style/images/app/ui/datausage/pattern.png" id="app-graphic-pattern" />
</section>

Expand Down
16 changes: 8 additions & 8 deletions apps/costcontrol/elements/datausage-tab.html
Expand Up @@ -3,14 +3,14 @@

<div class="view-scroll">
<section class="content">
<section id="graphic-area" class="graph">
<canvas id="background-layer"></canvas>
<canvas id="wifi-layer" hidden></canvas>
<canvas id="mobile-layer" hidden></canvas>
<canvas id="axis-layer"></canvas>
<canvas id="today-layer"></canvas>
<canvas id="warning-layer"></canvas>
<canvas id="limits-layer"></canvas>
<section id="graphic-area" class="graph" role="img" aria-labelledby="axis-layer today-layer limits-layer warning-layer">
<canvas id="background-layer" aria-hidden="true"></canvas>
<canvas id="wifi-layer" hidden aria-hidden="true"></canvas>
<canvas id="mobile-layer" hidden aria-hidden="true"></canvas>
<canvas id="axis-layer" aria-hidden="true"></canvas>
<canvas id="today-layer" aria-hidden="true"></canvas>
<canvas id="warning-layer" aria-hidden="true"></canvas>
<canvas id="limits-layer" aria-hidden="true"></canvas>
<img hidden alt="" src="./style/images/app/ui/datausage/pattern.png" id="graphic-pattern" />
</section>

Expand Down
33 changes: 33 additions & 0 deletions apps/costcontrol/js/utils/chart.js
Expand Up @@ -281,6 +281,8 @@ var ChartUtils = (function() {

ctx.fillStyle = 'black';
ctx.fillText(todayTag, offsetX, model.originY + marginTop);

setAccessibilityAttributes(canvas, 'today-layer', { today: todayTag });
}

function drawAxisLayer(canvas, model, showMobile) {
Expand Down Expand Up @@ -352,6 +354,22 @@ var ChartUtils = (function() {
if (!isBelowToday) {
ctx.fillText(rightTag, model.endX, model.originY + marginTop);
}

setAccessibilityAttributes(canvas, 'axis-layer',
{ from: leftTag, to: rightTag });
}

function setAccessibilityAttributes(element, identifier, data) {
if (identifier) {
element.setAttribute('data-l10n-id', identifier);
if (data) {
element.setAttribute('data-l10n-args', JSON.stringify(data));
}
} else {
element.removeAttribute('data-l10n-id');
element.removeAttribute('data-l10n-args');
element.removeAttribute('aria-label');
}
}

function drawLimits(canvas, model, showMobile) {
Expand Down Expand Up @@ -389,6 +407,10 @@ var ChartUtils = (function() {
ctx.stroke();

ctx.restore();

setAccessibilityAttributes(canvas,
'limit-layer-' + model.limits.dataLimitUnit,
{ value: model.limits.dataLimitValue });
}

function drawDataLayer(canvas, model, sampleType, style) {
Expand Down Expand Up @@ -491,12 +513,15 @@ var ChartUtils = (function() {
var ctx = canvas.getContext('2d');

if (!model.limits.enabled || model.limits.value === null) {
setAccessibilityAttributes(canvas);
return;
}

// No problem here
var mobileUsage = model.data.mobile.total;
var mobileUsageDifference = mobileUsage - model.limits.value;
if (mobileUsage <= model.limits.warningValue) {
setAccessibilityAttributes(canvas);
return;
}

Expand All @@ -512,6 +537,11 @@ var ChartUtils = (function() {
model.axis.X.len + 0.5, warningValue - limitValue
);

setAccessibilityAttributes(canvas, 'warning-layer', {
value: Formatting.formatData(Formatting.roundData(
-mobileUsageDifference))
});

return;
}

Expand All @@ -523,6 +553,9 @@ var ChartUtils = (function() {
model.originX, 0,
model.axis.X.len + 0.5, limitValueExceeded
);
setAccessibilityAttributes(canvas, 'limit-exceeded-layer', {
value: Formatting.formatData(Formatting.roundData(mobileUsageDifference))
});
}

return {
Expand Down
5 changes: 4 additions & 1 deletion apps/costcontrol/js/views/appdetail.js
Expand Up @@ -72,7 +72,9 @@ var AppDetailView = (function() {
},
limits: {
enabled: settings.dataLimit,
value: ChartUtils.getLimitInBytes(settings)
value: ChartUtils.getLimitInBytes(settings),
dataLimitValue: settings.dataLimitValue,
dataLimitUnit: settings.dataLimitUnit
},
data: {
wifi: {
Expand Down Expand Up @@ -190,6 +192,7 @@ var AppDetailView = (function() {

model.limits.enabled = settings.dataLimit;
model.limits.value = ChartUtils.getLimitInBytes(settings);
model.limits.dataLimitValue = settings.dataLimitValue;
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
ChartUtils.expandModel(model);
Expand Down
6 changes: 5 additions & 1 deletion apps/costcontrol/js/views/datausage.js
Expand Up @@ -77,7 +77,9 @@ var DataUsageTab = (function() {
},
limits: {
enabled: settings.dataLimit,
value: ChartUtils.getLimitInBytes(settings)
value: ChartUtils.getLimitInBytes(settings),
dataLimitValue: settings.dataLimitValue,
dataLimitUnit: settings.dataLimitUnit
},
data: {
wifi: {
Expand Down Expand Up @@ -226,6 +228,7 @@ var DataUsageTab = (function() {

model.limits.enabled = settings.dataLimit;
model.limits.value = ChartUtils.getLimitInBytes(settings);
model.limits.dataLimitValue = settings.dataLimitValue;
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
ChartUtils.expandModel(model);
Expand Down Expand Up @@ -263,6 +266,7 @@ var DataUsageTab = (function() {

function setDataLimit(value, old, key, settings) {
model.limits.value = ChartUtils.getLimitInBytes(settings);
model.limits.dataLimitValue = settings.dataLimitValue;
ChartUtils.expandModel(model);
drawCharts();
}
Expand Down
10 changes: 10 additions & 0 deletions apps/costcontrol/locales/costcontrol.en-US.properties
Expand Up @@ -215,3 +215,13 @@ data-used-since = {{amount}} of data used since {{start-date}}
data-used-this-week = {{amount}} of data used this week
data-used-this-month = {{amount}} of data used this month
data-usage-other-apps = Others

# LOCALIZATION NOTE: For charts the following labels are used to describe
# various layers drawn. The following strings are spoken by screen readers and
# not shown on the screen.
limit-layer-MB.ariaLabel = Limit of {{value}} MB
limit-layer-GB.ariaLabel = Limit of {{value}} GB
warning-layer.ariaLabel = {{value}} left
limit-exceeded-layer.ariaLabel = Exceeded by {{value}}
today-layer.ariaLabel = Today is {{today}}
axis-layer.ariaLabel = From {{from}} to {{to}}
91 changes: 90 additions & 1 deletion apps/costcontrol/test/unit/chart_utils_test.js
@@ -1,4 +1,4 @@
/* global ChartUtils, Toolkit, Common */
/* global ChartUtils, Toolkit, Common, Formatting */

'use strict';

Expand All @@ -7,6 +7,7 @@ require('/test/unit/mock_debug.js');
require('/test/unit/mock_moz_l10n.js');
require('/js/common.js');
require('/js/utils/toolkit.js');
require('/js/utils/formatting.js');
require('/js/utils/chart.js');

suite('ChartUtils suite >', function() {
Expand Down Expand Up @@ -224,4 +225,92 @@ suite('ChartUtils suite >', function() {
Common.DATA_USAGE_WARNING);
});

suite('accesibility', function() {
var canvas, model, date, upperDate, lowerDate;
function testAcesssibilityAttributes(identifier, data) {
assert.equal(canvas.getAttribute('data-l10n-id'), identifier);
assert.equal(canvas.getAttribute('data-l10n-args'), JSON.stringify(data));
}

setup(function() {
canvas = document.createElement('canvas');
date = new realDate(2014, 0, 15);
lowerDate = new realDate(2014, 0, 1);
upperDate = new realDate(2014, 0, 31);
model = {
axis: {
X: {
get: function() {},
today: date,
lower: lowerDate,
upper: upperDate
},
Y: { get: function() {}, lower: 0, margin: 0.20 }
},
data: {
wifi: { enabled: true, total: 0 },
mobile: { enabled: true, total: 0 }
},
todayLabel: {},
limits: {
enabled: true, value: null, dataLimitValue: 1, dataLimitUnit: 'MB'
}
};
});

test('> drawTodayLayer', function() {
ChartUtils.drawTodayLayer(canvas, model);
testAcesssibilityAttributes('today-layer',
{ today: ChartUtils.formatChartDate(date) });
});

test('> drawAxisLayer', function() {
ChartUtils.drawAxisLayer(canvas, model);
testAcesssibilityAttributes('axis-layer', {
from: ChartUtils.formatChartDate(lowerDate),
to: ChartUtils.formatChartDate(upperDate)
});
});

test('> drawLimits do not display limit', function() {
ChartUtils.drawLimits(canvas, model);
assert.isFalse(canvas.hasAttribute('data-l10n-id'));
assert.isFalse(canvas.hasAttribute('data-l10n-args'));
});

test('> drawLimits MB', function() {
ChartUtils.drawLimits(canvas, model, true);
testAcesssibilityAttributes('limit-layer-MB',
{ value: model.limits.dataLimitValue });
});

test('> drawLimits GB', function() {
model.limits.dataLimitUnit = 'GB';
ChartUtils.drawLimits(canvas, model, true);
testAcesssibilityAttributes('limit-layer-GB',
{ value: model.limits.dataLimitValue });
});

test('> drawWarningLayer do no warning', function() {
ChartUtils.drawWarningLayer(canvas, model);
assert.isFalse(canvas.hasAttribute('data-l10n-id'));
assert.isFalse(canvas.hasAttribute('data-l10n-args'));
});

test('> drawWarningLayer limit warning', function() {
model.limits.value = 10;
model.data.mobile.total = 9;
ChartUtils.drawWarningLayer(canvas, model);
testAcesssibilityAttributes('warning-layer',
{ value: Formatting.formatData(Formatting.roundData(1)) });
});

test('> drawWarningLayer limit exceeded', function() {
model.limits.value = 10;
model.data.mobile.total = 11;
ChartUtils.drawWarningLayer(canvas, model);
testAcesssibilityAttributes('limit-exceeded-layer',
{ value: Formatting.formatData(Formatting.roundData(1)) });
});
});
});

0 comments on commit 56a0369

Please sign in to comment.