Help us understand the problem. What is going on with this article?

アクセシブルネームを取得するjQueryプラグイン

More than 1 year has passed since last update.

とても久しぶりにjQueryを書くことになったので、
アクセシブルネームを取得するようなものを作ってみたり(何に使うんだ)。

/**
 * @see http://jquery.com/
 * @name fn
 * @class jQuery Library
 * @memberOf jQuery
 */

/**
 * 要素のアクセシブルネームを取得します
 * https://qiita.com/soten_bluesky/items/7e5d6d69893828cbf17e#comment-bc346c926f023fc5ac70
 * @return {string} 取得したアクセシブルネーム
 * @memberOf jQuery.fn
 * @license WTFPL 
 */
$.fn.getA11yName = function () {
    /**
     * @param {object} $self - jQueryオブジェクト
     * @return {string} aria-labelledby経由で取得を試みたアクセシブルネーム
     */
    const getAriaLabelledBy = ($self) => {
        const idList = $.trim($self.attr('aria-labelledby')).split(/\s/);
        let result = '';

        for (const id of idList) {
            result += `${$(document.getElementById(id)).text().trim()} `;
        }

        return result.trim();
    };
    /**
     * @param {object} $self - jQueryオブジェクト
     * @return {string} label要素経由で取得を試みたアクセシブルネーム
     */
    const getLabelElementTextContent = ($self) => {
        let result = '';
        const $allElm = $(document.getElementsByTagName('*'));
        const $closestLabel = $self.closest('label');
        const id = $self.attr('id');
        const labels = [];

        // 祖先のlabel要素
        if ($closestLabel.length) {
            labels.push({
                idx: $allElm.index($closestLabel),
                $node: $closestLabel.eq(0)
            });
        }

        // 祖先意外のlabel要素
        if (id) {
            const $labelingByForAttr = $(document.querySelectorAll(`label[for="${id}"]`));

            $labelingByForAttr.each(function () {
                const $label = $(this);

                labels.push({
                    idx: $allElm.index($label),
                    $node: $label
                });
            });
        }

        // 登場順に整理
        labels.sort(({idx: a}, {idx: b}) => a - b);

        for (const obj of labels) {
            result += `${obj.$node.text().trim()} `;
        }

        result = result.trim();

        // 結果的に中身が空でもlabel要素が見つかっていれば、
        // title属性を参照させないように空白文字を返す
        return result || (labels.length ? ' ' : '');
    };
    let result = '';

    this.each(function () {
        const $self = $(this);

        // アクセシブルネームの取得優先順に検証する
        result += (getAriaLabelledBy($self) || $self.attr('aria-label') || getLabelElementTextContent($self) || $self.attr('title') || '');
    });

    return result.trim();
};

使用方法

$('input').getA11yName(); // すべてのinput要素のアクセシブルネームを取得
$('input').eq(0).getA11yName(); // 1つのinput要素のアクセシブルネームを取得

謝辞

@htsign さんコードレビューありがとうございました!

heppokofrontend
最近RPAを始めたへっぽこフロントエンドエンジニア。 TypeScriptとかWebアクセシビリティに興味があります。
https://heppokofrontend.dev/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away