Skip to content

ARIA 支持

本章节主要包含如何快速运用 UIExtension 框架的内置功能实现可访问性,以及相关工具的介绍。如果你想详细了解 ARIA 的技术规范以及最佳实践,可以查阅以下的网址:

如何使用 UIExtension 启用可访问性

初始化 PDFUI 时,我们需要加载 aria 附加组件:

javascript
new UIExtension.PDFUI({
    addons: [
        // .... other Add-on
        'path/to/lib/uix-addons/aria/addon.info.json' // Make sure that aria is loaded last.
    ]
    // ... other options
})

如果你的应用程序是通过 allInOne.js 来加载插件,因为它已经包含 aria,所以不需要额外单独加载:

javascript
new UIExtension.PDFUI({
    addons: 'path/to/lib/uix-addons/allInOne.js'
    // ... other options
})

关于如何加载 add-on 的更详细信息,请参阅 Addons

UIExtension 内置组件

aria-label 属性

这些内置组件在指定 textlabel 参数后会自动向生成的 DOM 节点上添加 aria-label 属性,可点击 run 按钮运行示例, 然后使用屏幕阅读器查看效果:

html

<html>
<template id="layout-template">
    <webpdf>
        <div>
            <div>
                <gtab text="XButton" group="aria-tab" body="tab1-body" active></gtab>
                <gtab text="Dropdown" group="aria-tab" body="tab2-body"></gtab>
                <gtab text="Slider" group="aria-tab" body="tab3-body"></gtab>
                <gtab text="Ribbon button" group="aria-tab" body="tab4-body"></gtab>
            </div>
            <div name="tab1-body">
                <xbutton text="button"></xbutton>
            </div>
            <div name="tab2-body">
                <dropdown text="Dropdown" style="width: 8em" separate="false">
                    <xbutton text="Dropdown item 1"></xbutton>
                    <xbutton text="Dropdown item 2"></xbutton>
                </dropdown>
            </div>
            <div name="tab3-body">
                <slider min="0" max="100" step="1" label="Slider label"></slider>
            </div>
            <div name="tab4-body">
                <ribbon-button text="Ribbon button"></ribbon-button>
            </div>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

视觉隐藏的内容

在有些场景下,我们需要提供一些可供屏幕阅读器等辅助技术访问但视觉上隐藏的内容,并且通过使用 .fv__ui-aria-sr-only 类进行样式设置。这样可以为视觉障碍用户提供有用的信息或提示,比如使用不同的颜色表示危险、警告等不同类型的信息,这种情况下就需要添加额外文本内容告知视觉障碍用户这条信息的类型。

html
<p class="text-danger">
    <span class="fv__ui-aria-sr-only">Danger:</span>
    This action is not reversible.
</p>

aria 指令

@aria:attr 指令

该指令用于设置以 aria- 开头的属性,指令的写法是 @aria:attr.${aria-property-name}aria-property-name 可以参考 该网页,其参数值是一个可执行的表达式:

html

<html>
<template id="layout-template">
    <webpdf>
        <div @var.value="50">
            <input @aria:attr.valuemax="1" @aria:attr.valuemin="0" @aria:attr.valuenow="value + '%'">
            <!--Result:
                <input aria-valuemax="1" aria-valuemin="0" aria-valuenow="50%" ...>
            -->

            <!-- source text -->
            <input @aria:attr.label="'source text'">
            <!--Result:
                <input aria-label="source text" ...>
            -->

            <!-- I18n key -->
            <input @aria:attr.label="'aria:labels.gotopage'|i18n">
            <!--Result:
                <input aria-label="Set page" ...>
            -->
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

@aria:label 指令

该指令用于设置 aria-label 属性, 指令值为 i18n 词条。

html

<html>
<template id="layout-template">
    <webpdf>
        <div>
            <group-list>
                <group>
                    <input @aria:label="aria:labels.gotopage"
                           placeholder="@aria:label=&quot;aria:labels.gotopage&quot;">
                    <!--Result:
                        <input aria-label="Set page" ...>
                    -->

                    <!-- It is equivalent to: -->
                    <input @aria:attr.label="'aria:labels.gotopage'|i18n"
                           placeholder="@aria:attr.label=&quot;'aria:labels.gotopage'|i18n&quot;">
                    <!--Result:
                        <input aria-label="Set page" ...>
                    -->

                    <!-- source text -->
                    <input @aria:label="source text" placeholder="@aria:label=&quot;source text&quot;">
                    <!--Result:
                        <input aria-label="source text" ...>
                    -->
                    <!-- It is equivalent to: -->
                    <input @aria:attr.label="'source text'" placeholder="@aria:attr.label=&quot;'source text'&quot;">
                    <!--Result:
                        <input aria-label="source text" ...>
                    -->
                </group>
            </group-list>
            <group-list>
                <group>
                    <!-- It can set attributes at a location specified by the dropdown component -->
                    <!-- Set aria-label on the drop-down arrow -->
                    <dropdown @aria:label.caret="Toggle Dropdown" text="@aria:label.caret"></dropdown>
                </group>
                <group>
                    <!-- Set aria-label on icons -->
                    <dropdown icon-class="fv__icon-toolbar-hand" @aria:label.icon="Click dropdown icon"
                              text="@aria:label.icon"></dropdown>
                </group>
                <group>
                    <!-- Set aria-label on the input box -->
                    <dropdown
                            editable
                            @aria:label.editor="Click dropdown icon"
                            selected="1"
                            text="@aria:label.editor"
                    >
                        <dropdown-item>Item 2</dropdown-item>
                        <dropdown-item>Item 3</dropdown-item>
                        <dropdown-item>Item 1</dropdown-item>
                    </dropdown>
                </group>
                <group>
                    <!-- Set the aria-label of the list -->
                    <dropdown @aria:label.list="Items" text="@aria:label.list" separate="false">
                        <dropdown-item>Item 1</dropdown-item>
                        <dropdown-item>Item 2</dropdown-item>
                        <dropdown-item>Item 3</dropdown-item>
                    </dropdown>
                </group>
            </group-list>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

@aria:labelledby 指令

@aria:labelledby 指令用于生成 aria-labelledby 属性。指令值使用的是 UIExtension 的选择器语法,而不是元素的 id。这是因为 aria-labelledby 属性需要通过 id 关联到另外一个元素,而 id 可能引发全局冲突问题,因此我们不建议手写 id 来索引元素。该指令的选择器语法可以避免这一问题。

有关 aria-labelledby 属性的更详细信息,请查阅 该网址

html

<html>
<template id="layout-template">
    <webpdf>
        <div>
            <span>Field</span>
            <!-- This is just for demonstration -->
            <span name="a-colon">:</span>
            <input type="text" @aria:labelledby="::parent()::childAt(0),a-colon">
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

上述示例中,@aria:labelledby="::parent()::childAt(0),,a-colon" 指定了 <input> 前面两个 span 组件的 id 为标签。有关选择器语法更详细的信息,可以参阅 组件选择器

@aria:describedby 指令

@aria:describedby 指令的用法和原理和 @aria:labelledby 基本相同,此处不做过多说明。

有关 aria-describedby 更详细的信息,请查阅 该网址

html

<html>
<template id="layout-template">
    <webpdf>
        <div>
            <span>Field:</span>
            <input type="text" @aria:labelledby="::parent()::childAt(0)"
                   @aria:describedby="::nextSiblings(),more-description">
            <span class="fv__ui-aria-sr-only">
                    Description of text input.
                </span>
            <span class="fv__ui-aria-sr-only" name="more-description">
                    More description of text input.
                </span>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

@aria:rel 指令

ARIA 规范中,除了 aria-labelledbyaria-describedby 以外,还有很多需要关联其它元素的属性。@aria:rel 指令封装了这些常用的属性:

@aria:circular-focus 指令

该指令用来控制组件内元素的焦点,实现循环跳转功能。通常用于弹窗或者一个独立的 UI 区域。

可参照下面的示例,点击 run 按钮运行。

html

<html>
<template id="layout-template">
    <webpdf>
        <div>
            <group-list>
                <group>
                    <xbutton>button 1</xbutton>
                    <xbutton>button 2</xbutton>
                    <xbutton>button 3</xbutton>
                </group>
                <group @aria:circular-focus>
                    <xbutton @tooltip
                             tooltip-title="Press 'Shift + Tab' will switch focus to 'button 6' instead of 'button 3'">
                        button 4
                    </xbutton>
                    <xbutton>button 5</xbutton>
                    <xbutton @tooltip tooltip-title="Press 'Tab' will switch focus to 'button 4' instead of 'button 7'">
                        button 6
                    </xbutton>
                </group>
                <group>
                    <xbutton>button 7</xbutton>
                </group>
            </group-list>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}