Skip to content

Commit 669e1f6

Browse files
author
michael-n-cooper
committed
Generated by TRAVIS-CI 96e5afd
Add meter example for issue 1105 (pull #1190) Resolves #1105 by adding a CPU meter display that implements the meter pattern.
1 parent e9deea6 commit 669e1f6

File tree

4 files changed

+332
-5
lines changed

4 files changed

+332
-5
lines changed

examples/meter/css/meter.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
[role=meter] {
3+
padding: 2px;
4+
width: 200px;
5+
height: 40px;
6+
border: 2px solid black;
7+
border-radius: 5px;
8+
}
9+
10+
.fill {
11+
width: 100%;
12+
height: 100%;
13+
box-sizing: border-box;
14+
border: 2px solid black;
15+
border-radius: 3px;
16+
background-color: black;
17+
}

examples/meter/js/meter.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
var Meter = function (element) {
2+
this.rootEl = element;
3+
this.fillEl = element.querySelector('.fill');
4+
5+
// set up min, max, and current value
6+
var min = element.getAttribute('aria-valuemin');
7+
var max = element.getAttribute('aria-valuemax');
8+
var value = element.getAttribute('aria-valuenow');
9+
this._update(parseFloat(min), parseFloat(max), parseFloat(value));
10+
};
11+
12+
/* Private methods */
13+
14+
// returns a number representing a percentage between 0 - 100
15+
Meter.prototype._calculatePercentFill = function (min, max, value) {
16+
if (typeof min !== 'number' || typeof max !== 'number' || typeof value !== 'number') {
17+
return 0;
18+
}
19+
20+
return 100 * (value - min) / (max - min);
21+
};
22+
23+
// returns an hsl color string between red and green
24+
Meter.prototype._getColorValue = function (percent) {
25+
// red is 0deg, green is 120deg in hsl
26+
// if percent is 100, hue should be red, and if percent is 0, hue should be green
27+
var hue = (percent / 100) * (0 - 120) + 120;
28+
29+
return 'hsl(' + hue + ', 100%, 40%)';
30+
};
31+
32+
// no return value; updates the meter element
33+
Meter.prototype._update = function (min, max, value) {
34+
// update fill width
35+
if (min !== this.min || max !== this.max || value !== this.value) {
36+
var percentFill = this._calculatePercentFill(min, max, value);
37+
this.fillEl.style.width = percentFill + '%';
38+
this.fillEl.style.color = this._getColorValue(percentFill);
39+
}
40+
41+
// update aria attributes
42+
if (min !== this.min) {
43+
this.min = min;
44+
this.rootEl.setAttribute('aria-valuemin', min + '');
45+
}
46+
47+
if (max !== this.max) {
48+
this.max = max;
49+
this.rootEl.setAttribute('aria-valuemax', max + '');
50+
}
51+
52+
if (value !== this.value) {
53+
this.value = value;
54+
this.rootEl.setAttribute('aria-valuenow', value + '');
55+
}
56+
};
57+
58+
/* Public methods */
59+
60+
// no return value; modifies the meter element based on a new value
61+
Meter.prototype.setValue = function (value) {
62+
if (typeof value !== 'number') {
63+
value = parseFloat(value);
64+
}
65+
66+
if (!isNaN(value)) {
67+
this._update(this.min, this.max, value);
68+
}
69+
};
70+
71+
/* Code for example page */
72+
73+
window.addEventListener('load', function () {
74+
// helper function to randomize example meter value
75+
function getRandomValue (min, max) {
76+
var range = max - min;
77+
return Math.floor((Math.random() * range) + min);
78+
}
79+
80+
// init meters
81+
var meterEls = document.querySelectorAll('[role=meter]');
82+
var meters = [];
83+
Array.prototype.slice.call(meterEls).forEach(function (meterEl) {
84+
meters.push(new Meter(meterEl));
85+
});
86+
87+
// randomly update meter values
88+
89+
// returns an id for setInterval
90+
function playMeters () {
91+
return window.setInterval(function () {
92+
meters.forEach(function (meter) {
93+
meter.setValue(Math.random() * 100);
94+
});
95+
}, 5000);
96+
}
97+
98+
// start meters
99+
var updateInterval = playMeters();
100+
101+
// play/pause meter updates
102+
var playButton = document.querySelector('.play-meters');
103+
playButton.addEventListener('click', function () {
104+
var isPaused = playButton.classList.contains('paused');
105+
106+
if (isPaused) {
107+
updateInterval = playMeters();
108+
playButton.classList.remove('paused');
109+
playButton.innerHTML = 'Pause Updates';
110+
}
111+
else {
112+
clearInterval(updateInterval);
113+
playButton.classList.add('paused');
114+
playButton.innerHTML = 'Start Updates';
115+
}
116+
});
117+
});

examples/meter/meter.html

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Meter Example | WAI-ARIA Authoring Practices 1.1</title>
5+
<!-- Core js and css shared by all examples; do not modify when using this template. -->
6+
<link rel="stylesheet" href="https://www.w3.org/StyleSheets/TR/2016/base.css">
7+
<link rel="stylesheet" href="../css/core.css">
8+
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
9+
10+
<script src="../js/examples.js" type="text/javascript"></script>
11+
<script src="../js/highlight.pack.js"></script>
12+
<script src="../js/app.js"></script>
13+
14+
<!-- CSS and JS for this example. -->
15+
<link rel="stylesheet" href="css/meter.css">
16+
<script src="js/meter.js" type="text/javascript"></script>
17+
18+
</head>
19+
<body>
20+
<nav aria-label="Related Links" class="feedback">
21+
<ul>
22+
<li><a href="../../../#browser_and_AT_support">Browser and Assistive Technology Support</a></li>
23+
<li><a href="https://github.com/w3c/aria-practices/issues/new">Report Issue</a></li>
24+
<li><a href="https://github.com/w3c/aria-practices/projects/30">Related Issues</a></li>
25+
<li><a href="../../#meter">Design Pattern</a></li>
26+
</ul>
27+
</nav>
28+
<main>
29+
<h1> Meter Example</h1>
30+
<p>The following example of a CPU meter demonstrates the <a href="../../#meter">meter design pattern</a>.</p>
31+
32+
<section>
33+
<h2 id="ex_label">Example</h2>
34+
<div role="separator" id="ex_start_sep" aria-labelledby="ex_start_sep ex_label" aria-label="Start of"></div>
35+
36+
<div id="example">
37+
<p>The value of this meter changes every 5 seconds. Use the pause button to stop changes.</p>
38+
<h3 id="cpu_usage_label">Central Processing Unit (CPU) Usage</h3>
39+
<p>
40+
<button type="button" class="play-meters">Pause Updates</button>
41+
</p>
42+
<div role="meter" aria-valuenow="90" aria-valuemin="0" aria-valuemax="100" aria-labelledby="cpu_usage_label">
43+
<svg width="100" height="100" class="fill" aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg">
44+
<rect x="0" y="0" width="100%" height="100%" fill="currentColor" />
45+
</svg>
46+
</div>
47+
</div>
48+
<div role="separator" id="ex_end_sep" aria-labelledby="ex_end_sep ex_label" aria-label="End of"></div>
49+
</section>
50+
<section>
51+
<h2 id="kbd_label">Keyboard Support</h2>
52+
<p>Not applicable.</p>
53+
</section>
54+
55+
<section>
56+
<h2 id="rps_label">Role, Property, State, and Tabindex Attributes</h2>
57+
<table aria-labelledby="rps_label" class="data attributes">
58+
<thead>
59+
<tr>
60+
<th scope="col">Role</th>
61+
<th scope="col">Attribute</th>
62+
<th scope="col">Element</th>
63+
<th scope="col">Usage</th>
64+
</tr>
65+
</thead>
66+
<tbody>
67+
<tr data-test-id="meter-role">
68+
<th scope="row"><code>meter</code></th>
69+
<td></td>
70+
<td>
71+
<code>div</code>
72+
</td>
73+
<td>
74+
<ul>
75+
<li>Identifies the element as a <code>meter</code>.</li>
76+
</ul>
77+
</td>
78+
</tr>
79+
<tr data-test-id="meter-aria-valuemin">
80+
<td></td>
81+
<th scope="row"><code>aria-valuemin="NUMBER"</code></th>
82+
<td><code>div</code></td>
83+
<td>Specifies the minimum value the meter can have.</td>
84+
</tr>
85+
<tr data-test-id="meter-aria-valuemax">
86+
<td></td>
87+
<th scope="row"><code>aria-valuemax="NUMBER"</code></th>
88+
<td><code>div</code></td>
89+
<td>Specifies the maximum value the meter can have.</td>
90+
</tr>
91+
<tr data-test-id="meter-aria-valuenow">
92+
<td></td>
93+
<th scope="row"><code>aria-valuenow="NUMBER"</code></th>
94+
<td><code>div</code></td>
95+
<td>Specifies the current value of the meter.</td>
96+
</tr>
97+
<tr data-test-id="meter-aria-labelledby">
98+
<td></td>
99+
<th scope="row"><code>aria-labelledby</code></th>
100+
<td><code>div</code></td>
101+
<td>Identifies the element that provides the accessible name of the <code>meter</code>.</td>
102+
</tr>
103+
</tbody>
104+
</table>
105+
</section>
106+
107+
<section>
108+
<h2>Javascript and CSS Source Code</h2>
109+
110+
<ul>
111+
<li>
112+
CSS:
113+
<a href="css/meter.css" type="text/css">meter.css</a>
114+
</li>
115+
<li>
116+
Javascript:
117+
<a href="js/meter.js" type="text/javascript">meter.js</a>
118+
</li>
119+
</ul>
120+
</section>
121+
122+
<section>
123+
<h2 id="sc1_label">HTML Source Code</h2>
124+
125+
<div role="separator" id="sc1_start_sep" aria-labelledby="sc1_start_sep sc1_label" aria-label="Start of"></div>
126+
127+
<pre><code id="source1"></code></pre>
128+
129+
<div role="separator" id="sc1_end_sep" aria-labelledby="sc1_end_sep sc1_label" aria-label="End of"></div>
130+
131+
<script>
132+
sourceCode.add('source1', 'example');
133+
sourceCode.make();
134+
</script>
135+
</section>
136+
</main>
137+
138+
<nav>
139+
<a href="../../#meter">Meter Design Pattern in WAI-ARIA Authoring Practices 1.1</a>
140+
</nav>
141+
</body>
142+
</html>

0 commit comments

Comments
 (0)