Tóm tắt
<howto-checkbox>
đại diện cho một tuỳ chọn boolean trong biểu mẫu. Loại phổ biến nhất
hộp đánh dấu là loại kép cho phép người dùng chuyển đổi giữa
lựa chọn -- đã đánh dấu và bỏ đánh dấu.
Phần tử này cố gắng tự áp dụng các thuộc tính role="checkbox"
và
tabindex="0"
khi được tạo lần đầu. Thuộc tính role
giúp hỗ trợ
như trình đọc màn hình cho người dùng biết đây là loại kiểm soát nào.
Thuộc tính tabindex
chọn phần tử này trong thứ tự thẻ, giúp phần tử này trở thành bàn phím
có thể làm tâm điểm và có thể hoạt động. Để tìm hiểu thêm về hai chủ đề này, hãy xem
ARIA có thể làm gì? và Sử dụng chỉ mục thẻ.
Khi bạn đánh dấu vào hộp này, thao tác này sẽ thêm thuộc tính boolean checked
và đặt
một thuộc tính checked
tương ứng với true
. Ngoài ra, phần tử này còn đặt
một
thuộc tính aria-checked
cho "true"
hoặc "false"
, tuỳ thuộc vào
trạng thái. Nhấp vào hộp đánh dấu bằng chuột hoặc thanh dấu cách, sẽ bật/tắt các tuỳ chọn này
trạng thái đã đánh dấu.
Hộp đánh dấu này cũng hỗ trợ trạng thái disabled
. Nếu thuộc tính disabled
được đặt thành true hoặc áp dụng thuộc tính disabled
, hộp đánh dấu sẽ được đặt
aria-disabled="true"
, xoá thuộc tính tabindex
và trả về tiêu điểm
vào tài liệu nếu hộp đánh dấu là activeElement
hiện tại.
Hộp đánh dấu này được ghép nối với phần tử howto-label
để đảm bảo phần tử này có
tên dễ tiếp cận.
Tài liệu tham khảo
- HowTo: Các thành phần trên GitHub
- Mẫu hộp kiểm trong phương pháp ghi nhận quyền tác giả ARIA 1.1
- ARIA có thể làm gì?
- Sử dụng chỉ mục thẻ
Bản minh hoạ
Xem bản minh hoạ trực tiếp trên GitHub
Ví dụ về cách sử dụng
<style>
howto-checkbox {
vertical-align: middle;
}
howto-label {
vertical-align: middle;
display: inline-block;
font-weight: bold;
font-family: sans-serif;
font-size: 20px;
margin-left: 8px;
}
</style>
<howto-checkbox id="join-checkbox"></howto-checkbox>
<howto-label for="join-checkbox">Join Newsletter</howto-label>
Mã
(function() {
Xác định các mã phím để giúp xử lý các sự kiện trên bàn phím.
const KEYCODE = {
SPACE: 32,
};
Việc sao chép nội dung từ phần tử <template>
hiệu quả hơn so với sử dụng innerHTML vì nó giúp tránh phát sinh thêm chi phí phân tích cú pháp HTML.
const template = document.createElement('template');
template.innerHTML = `
<style>
:host {
display: inline-block;
background: url('../images/unchecked-checkbox.svg') no-repeat;
background-size: contain;
width: 24px;
height: 24px;
}
:host([hidden]) {
display: none;
}
:host([checked]) {
background: url('../images/checked-checkbox.svg') no-repeat;
background-size: contain;
}
:host([disabled]) {
background:
url('../images/unchecked-checkbox-disabled.svg') no-repeat;
background-size: contain;
}
:host([checked][disabled]) {
background:
url('../images/checked-checkbox-disabled.svg') no-repeat;
background-size: contain;
}
</style>
`;
class HowToCheckbox extends HTMLElement {
static get observedAttributes() {
return ['checked', 'disabled'];
}
Hàm khởi tạo của phần tử sẽ chạy mỗi khi có một thực thể mới được tạo. Các đối tượng được tạo bằng cách phân tích cú pháp HTML, gọi document.createElement('howto-checkbox') hoặc gọi HowToCheckbox(); mới Hàm dựng là nơi thích hợp để tạo DOM bóng, mặc dù bạn nên tránh chạm vào bất kỳ thuộc tính nào hoặc phần tử con DOM sáng vì các thuộc tính này có thể chưa có sẵn.
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback()
kích hoạt khi phần tử được chèn vào DOM. Bạn nên thiết lập role
, tabindex
ban đầu, trạng thái nội bộ và trình nghe sự kiện cài đặt.
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
Người dùng có thể đặt thuộc tính trên một thực thể của một phần tử, trước khi nguyên mẫu của phần tử đó được kết nối với lớp này. Phương thức _upgradeProperty()
sẽ kiểm tra mọi thuộc tính thực thể và chạy các thuộc tính đó thông qua phương thức setter lớp thích hợp. Hãy xem phần thuộc tính từng phần để biết thêm thông tin.
this._upgradeProperty('checked');
this._upgradeProperty('disabled');
this.addEventListener('keyup', this._onKeyUp);
this.addEventListener('click', this._onClick);
}
_upgradeProperty(prop) {
if (this.hasOwnProperty(prop)) {
let value = this[prop];
delete this[prop];
this[prop] = value;
}
}
disconnectedCallback()
kích hoạt khi phần tử bị xoá khỏi DOM. Đây là nơi thích hợp để dọn dẹp các công việc như phát hành tệp đối chiếu và xoá trình nghe sự kiện.
disconnectedCallback() {
this.removeEventListener('keyup', this._onKeyUp);
this.removeEventListener('click', this._onClick);
}
Các thuộc tính và các thuộc tính tương ứng phải đồng bộ hoá hai chiều. Phương thức setter thuộc tính cho mục đã kiểm tra sẽ xử lý các giá trị đúng/sai và phản ánh các giá trị đó cho trạng thái của thuộc tính. Hãy xem phần tránh tỷ lệ lặp lại để biết thêm chi tiết.
set checked(value) {
const isChecked = Boolean(value);
if (isChecked)
this.setAttribute('checked', '');
else
this.removeAttribute('checked');
}
get checked() {
return this.hasAttribute('checked');
}
set disabled(value) {
const isDisabled = Boolean(value);
if (isDisabled)
this.setAttribute('disabled', '');
else
this.removeAttribute('disabled');
}
get disabled() {
return this.hasAttribute('disabled');
}
attributeChangedCallback()
được gọi khi bất kỳ thuộc tính nào trong mảngObserveAttributes thay đổi. Đây là một nơi phù hợp để xử lý các tác dụng phụ, chẳng hạn như đặt các thuộc tính ARIA.
attributeChangedCallback(name, oldValue, newValue) {
const hasValue = newValue !== null;
switch (name) {
case 'checked':
this.setAttribute('aria-checked', hasValue);
break;
case 'disabled':
this.setAttribute('aria-disabled', hasValue);
Thuộc tính tabindex
không cung cấp cách thức để xoá hoàn toàn khả năng lấy tiêu điểm khỏi một phần tử. Bạn vẫn có thể lấy tiêu điểm các phần tử có tabindex=-1
bằng chuột hoặc bằng cách gọi focus()
. Để đảm bảo rằng một phần tử bị tắt và không thể lấy tiêu điểm, hãy xoá thuộc tính tabindex
.
if (hasValue) {
this.removeAttribute('tabindex');
Nếu tiêu điểm đang nằm trên phần tử này, thì hãy huỷ lấy tiêu điểm bằng cách gọi phương thức HTMLElement.blur()
this.blur();
} else {
this.setAttribute('tabindex', '0');
}
break;
}
}
_onKeyUp(event) {
Không xử lý các phím tắt thường dùng của công nghệ hỗ trợ.
if (event.altKey)
return;
switch (event.keyCode) {
case KEYCODE.SPACE:
event.preventDefault();
this._toggleChecked();
break;
Mọi thao tác nhấn phím khác sẽ bị bỏ qua và chuyển trở lại trình duyệt.
default:
return;
}
}
_onClick(event) {
this._toggleChecked();
}
_toggleChecked()
gọi phương thức setter đã kiểm tra và lật trạng thái của phương thức này. Vì _toggleChecked()
chỉ do hành động của người dùng gây ra, nên mã này cũng sẽ gửi một sự kiện thay đổi. Sự kiện này tạo bong bóng trò chuyện để bắt chước hành vi gốc của <input type=checkbox>
.
_toggleChecked() {
if (this.disabled)
return;
this.checked = !this.checked;
this.dispatchEvent(new CustomEvent('change', {
detail: {
checked: this.checked,
},
bubbles: true,
}));
}
}
customElements.define('howto-checkbox', HowToCheckbox);
})();