TEST
WAI-ARIA メモ
最終更新:
eriax
-
view
aria-controls による連動型選択肢
<!DOCTYPE html> <title>TEST</title> <style type="text/css"> @media screen { *[aria-hidden="true"] { display: none; } *.aria-hidden { display: none; } } </style> <script type="text/javascript"> var _GenerateAssociation = function () { var _SetAriaHidden_Select = function () { return function SetAriaHidden_Select (select) { var controls = select.getAttribute ('aria-controls'); if (! controls) { return; } controls = controls.split (/\s+/); var index = select.selectedIndex - 1; var count = controls.length; var d = select.ownerDocument; var i; var n; for (i = 0; i < index; ++i) { n = d.getElementById (controls[i]); if (! n) { continue; } if (n.getAttribute ('aria-hidden') !== 'true') { n.setAttribute ('aria-hidden', 'true'); _AddClass (n, 'aria-hidden'); } _SetAriaHidden_All (n, true); } if (index < 0) { _SetAriaHidden_All (select, true); } else { n = d.getElementById (controls[index]); if (n) { n.setAttribute ('aria-hidden', 'false'); _RemoveClass (n, 'aria-hidden'); try { var e = d.createEvent ('HTMLEvents'); e.initEvent ('change', false, false); n.dispatchEvent (e); } catch (err) { n.fireEvent ('onchange'); } } } for (i += 1; i < count; ++i) { n = d.getElementById (controls[i]); if (! n) { continue; } if (n.getAttribute ('aria-hidden') !== 'true') { n.setAttribute ('aria-hidden', 'true'); _AddClass (n, 'aria-hidden'); } _SetAriaHidden_All (n, true); } }; } (); var _SetAriaHidden_All = function () { return function SetAriaHidden_All (elt, hidden) { var controls = elt.getAttribute ('aria-controls'); if (! controls) { return; } controls = controls.split (/\s+/); hidden = String (hidden); var count = controls.length; var d = elt.ownerDocument; var i; var n; for (i = 0; i < count; ++i) { n = d.getElementById (controls[i]); if (! n) { continue; } n.setAttribute ('aria-hidden', hidden); _AddClass (n, 'aria-hidden'); SetAriaHidden_All (n, hidden); } }; } (); var _AddClass = function () { return function AddClass (elt, className) { var c = elt.className; k = className.replace (/\W/g, '$&'); if (! new RegExp ('(?:^|\s)' + k + '(?:\s|$)').test (c)) { c += '\x20' + className; elt.className = c.replace (/^\s+|\s+$/g, '').replace (/\s+/g, '\x20'); } }; } (); var _RemoveClass = function () { return function RemoveClass (elt, className) { var c = elt.className; k = className.replace (/\W/g, '$&'); if (new RegExp ('(?:^|\s)' + k + '(?:\s|$)').test (c)) { c = c.replace (new RegExp (k), ''); elt.className = c.replace (/^\s+|\s+$/g, '').replace (/\s+/g, '\x20'); } }; } (); return function () { return function GenerateAssociation (startIDs) { return function handleEvent (e) { switch (e.type) { case 'load' : var count = startIDs.length; var d = e.target || this.document; var i; var c; for (i = 0; i < count; ++i) { c = d.getElementById (startIDs[i]); if (c) { _SetAriaHidden_All (c, true); _SetAriaHidden_Select (c); } } return; case 'change' : var c = e.currentTarget || this; _SetAriaHidden_Select (c); return; } }; }; } (); } (); var anAssociation1 = _GenerateAssociation ([ 'start' ]); </script> <body onload="return anAssociation1.call (this, event);"> <form action="#"> <p> <select id="start" aria-controls="C1 C2 C3" onchange="return anAssociation1.call (this, event);"> <option>-</option> <option>Category 1</option> <option>Category 2</option> <option>Category 3</option> </select> <select id="C1" aria-controls="C1-1 C1-2 C1-3" onchange="return anAssociation1.call (this, event);"> <option>-</option> <option>Category 1-1</option> <option>Category 1-2</option> <option>Category 1-3</option> </select> <select id="C1-1"> <option>-</option> <option>Category 1-1-1</option> <option>Category 1-1-2</option> <option>Category 1-1-3</option> </select> <select id="C1-2"> <option>-</option> <option>Category 1-2-1</option> <option>Category 1-2-2</option> <option>Category 1-2-3</option> </select> <select id="C1-3"> <option>-</option> <option>Category 1-3-1</option> <option>Category 1-3-2</option> <option>Category 1-3-3</option> </select> <select id="C2" aria-controls="C2-1 C2-2 C2-3" onchange="return anAssociation1.call (this, event);"> <option>-</option> <option>Category 2-1</option> <option>Category 2-2</option> <option>Category 2-3</option> </select> <select id="C2-1"> <option>-</option> <option>Category 2-1-1</option> <option>Category 2-1-2</option> <option>Category 2-1-3</option> </select> <select id="C2-2"> <option>-</option> <option>Category 2-2-1</option> <option>Category 2-2-2</option> <option>Category 2-2-3</option> </select> <select id="C2-3"> <option>-</option> <option>Category 2-3-1</option> <option>Category 2-3-2</option> <option>Category 2-3-3</option> </select> <select id="C3" aria-controls="C3-1 C3-2 C3-3" onchange="return anAssociation1.call (this, event);"> <option>-</option> <option>Category 3-1</option> <option>Category 3-2</option> <option>Category 3-3</option> </select> <select id="C3-1"> <option>-</option> <option>Category 3-1-1</option> <option>Category 3-1-2</option> <option>Category 3-1-3</option> </select> <select id="C3-2"> <option>-</option> <option>Category 3-2-1</option> <option>Category 3-2-2</option> <option>Category 3-2-3</option> </select> <select id="C3-3"> <option>-</option> <option>Category 3-3-1</option> <option>Category 3-3-2</option> <option>Category 3-3-3</option> </select> </p> </form>
aria-controls と aria-labelledby
<!DOCTYPE html> <title>TEST</title> <body> <form action="#" onclick=" var target = event.target || event.srcElement; var currentTarget = event.currentTarget || this; var doc = target.ownerDocument; switch (target.tagName) { case 'IMG' : var source = target; var result; var t; for (t = target; t; t = t.parentNode) { result = t.getAttribute ('aria-controls'); if (result) { result = doc.getElementById (result); if (! result) { break; } if (result.tagName === 'IMG') { result.src = source.src; result.alt = source.alt; } break; } if (t === currentTarget) { break; } } return; case 'INPUT' : var sources = target.getAttribute ('aria-labelledby'); var source; var results; var result; var t; var i; if (! sources) { return; } sources = sources.replace (/^\s+|\s+$/g, '').replace (/\s+/g, '\x20').split (/\x20/); for (i = 0; source = sources[i]; ++i) { source = doc.getElementById (source); sources[i] = source ? (source.tagName === 'IMG') ? source : null : null; } for (t = target; t; t = t.parentNode) { results = t.getAttribute ('aria-controls'); if (results) { results = results.replace (/^\s+|\s+$/g, '').replace (/\s+/g, '\x20').split (/\x20/); for (i = 0; result = results[i]; ++i) { source = sources[i]; if (! source) { continue; } result = doc.getElementById (result); if (! result) { continue; } if (result.tagName === 'IMG') { result.src = source.src; result.alt = source.alt; } } } if (t === currentTarget) { break; } } return; } "> <fieldset> <legend>画像を選んで下さい</legend> <ul> <li aria-controls="A"> <span>A グループ:</span> <img id="A0" src="A0.png" alt="A0"> <img id="A1" src="A1.png" alt="A1"> <img id="A2" src="A2.png" alt="A2"> <img id="A3" src="A3.png" alt="A3"> </li> <li aria-controls="B"> <span>B グループ:</span> <img id="B0" src="B0.png" alt="B0"> <img id="B1" src="B1.png" alt="B1"> </li> <li aria-controls="C"> <span>C グループ:</span> <img id="C0" src="C0.png" alt="C0"> <img id="C1" src="C1.png" alt="C1"> <img id="C2" src="C2.png" alt="C2"> </li> </ul> <ul> <li aria-controls="A B C"> <input type="button" value="お勧めの組み合わせ 1" aria-labelledby="A0 B0 C1"> <input type="button" value="お勧めの組み合わせ 2" aria-labelledby="A3 B1 C0"> <input type="button" value="お勧めの組み合わせ 3" aria-labelledby="A2 B1 C1"> </li> </ul> <img src="0.png" alt="dummy"> </fieldset> <fieldset> <legend>結果</legend> <p> <img id="A" src="blank.png" alt="*"> <img id="B" src="blank.png" alt="*"> <img id="C" src="blank.png" alt="*"> </p> </fieldset> </form>