Skip to content

Instantly share code, notes, and snippets.

@svict4
Last active May 6, 2018 12:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svict4/f7e757ce94f4796259299c93fc34ca49 to your computer and use it in GitHub Desktop.
Save svict4/f7e757ce94f4796259299c93fc34ca49 to your computer and use it in GitHub Desktop.
accessible aria-label header links in div-ul-li-a table

An accessible way to listen to the newly sorted headers of a horrible data table/list structure like so:

<div>
    <dl>
        <ul>
            <li>
                <a></a>
            </li>
        </ul>
    </dl>
</div>

See the example.html

$(document).ready(function () {
    $("div.listitemsort a").on("click", function () {
        var $listElement = $(this).parent(),
            $headerList = $listElement.parent();

        if ($headerList.data("sortedColumn")) {
            // new listitem selected, remove sort on existing item
            if ($headerList.data("sortedColumn") !== $listElement.attr("id")) {
                removeSort($headerList);
            }
        } else {
            // ensure that original label doesn't change
            $headerList.data({
                "originalLabel": $listElement.attr("aria-label")
            });
        }
        setSort($headerList, $listElement);
    });

    // WONTFIX: this means it'll fire every time we focus away, even if it's not sorted
    // but due to old enterprise system, it is less expensive to throw this into the relevant lifecycle hook
    $("div.listitemsort a").on("focusout", function () {
        // if we have sorted item, remove the "currently sorted descending" if it's there
        var $listElement = $(this).parent(),
            $headerList = $listElement.parent();

        if ($headerList.data("sortedColumn") == $listElement.attr("id")) {
            $listElement.attr("aria-label", $headerList.data("originalLabel"))
        }
    });

    function setSort($headerList, $listElement) {
        // assumption that only one column can be sorted at a time
        switch ($headerList.data("sort-direction")) {
            case "descending":
                // set ascending
                setSortAttributes($headerList, $listElement, "ascending");
                break;
            default:
            // undefined, must be first time clicked or is not descending/ascending algorithm
            // fall-through
            case "ascending":
                // set descending
                setSortAttributes($headerList, $listElement, "descending");
                break;
        }
    };

    function setSortAttributes($headerList, $listElement, direction) {
        $headerList.data({
            "sort-direction": direction,
            "sortedColumn": $listElement.attr("id")
        });

        $listElement.attr({
            "aria-sort": direction,
            "sort-direction": direction,
            "aria-label": $headerList.data("originalLabel") + " - " + "currently sorted " + direction
        });
    }

    function removeSort($headerList) {
        $("#" + $headerList.data("sortedColumn")).attr({
            "aria-sort": "none",
            "sort-direction": "default",
            "aria-label": $headerList.data("originalLabel")
        });
    }
});
<!doctype html>
<html lang="en">
<head>
<title>
accessible aria-labels on header links
</title>
<meta charset="utf-8">
<style>
body {
margin: 5em auto;
width: 40em;
}
li:hover {
background: #adadad;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("div.listitemsort a").on("click", function () {
var $listElement = $(this).parent(),
$headerList = $listElement.parent();
if ($headerList.data("sortedColumn")) {
// new listitem selected, remove sort on existing item
if ($headerList.data("sortedColumn") !== $listElement.attr("id")) {
removeSort($headerList);
}
} else {
// ensure that original label doesn't change
$headerList.data({
"originalLabel": $listElement.attr("aria-label")
});
}
setSort($headerList, $listElement);
});
$("div.listitemsort a").on("focusout", function () {
// if we have sorted item, remove the "currently sorted descending" if it's there
var $listElement = $(this).parent(),
$headerList = $listElement.parent();
if ($headerList.data("sortedColumn") == $listElement.attr("id")) {
$listElement.attr("aria-label", $headerList.data("originalLabel"))
}
});
function setSort($headerList, $listElement) {
// assumption that only one column can be sorted at a time
switch ($headerList.data("sort-direction")) {
case "descending":
// set ascending
setSortAttributes($headerList, $listElement, "ascending");
break;
default:
// undefined, must be first time clicked or is not descending/ascending algorithm
// fall-through
case "ascending":
// set descending
setSortAttributes($headerList, $listElement, "descending");
break;
}
};
function setSortAttributes($headerList, $listElement, direction) {
$headerList.data({
"sort-direction": direction,
"sortedColumn": $listElement.attr("id")
});
$listElement.attr({
"aria-sort": direction,
"sort-direction": direction,
"aria-label": $headerList.data("originalLabel") + " - " + "currently sorted " + direction
});
}
function removeSort($headerList) {
$("#" + $headerList.data("sortedColumn")).attr({
"aria-sort": "none",
"sort-direction": "default",
"aria-label": $headerList.data("originalLabel")
});
}
});
</script>
</head>
<body>
<div>
<a href="#">focus start</a>
</div>
<div style="height: 5em; width: 100%;"></div>
<div class="listitemsort">
<dl>
<ul aria-label="Click to sort the following items">
<li control-name="I am item one" role="columnheader" sort-direction="default" aria-sort="none" aria-label="I am header one - sortable"
tabindex="-1" id="1">
<a href="javascript:;" aria-hidden="true">I am header one</a>
</li>
<li control-name="I am header two" role="columnheader" sort-direction="default" aria-sort="none" aria-label="I am header two - sortable"
tabindex="-1" id="2">
<a href="javascript:;" aria-hidden="true">I am header two</a>
</li>
<li control-name="I am header three" role="columnheader" sort-direction="default" aria-sort="none" aria-label="I am header three - sortable"
tabindex="-1" id="3">
<a href="javascript:;" aria-hidden="true">I am header three</a>
</li>
</ul>
</dl>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment