ملخّص
يمثّل الرمز <howto-checkbox>
خيارًا منطقيًا في نموذج. النوع الأكثر شيوعًا
من مربّعات الاختيار هو النوع المزدوج الذي يسمح للمستخدم بالتبديل بين خيارين
: محدَّد بعلامة وغير محدَّد بعلامة.
يحاول العنصر تطبيق السمتين role="checkbox"
وtabindex="0"
ذاتيًا
عند إنشائه لأول مرة. تساعد سمة role
التكنولوجيا
المساعدة، مثل قارئ الشاشة، في إخبار المستخدم بنوع عنصر التحكّم هذا.
تُضيف سمة tabindex
العنصر إلى ترتيب علامات التبويب، ما يجعله قابلاً للتركيز عليه باستخدام لوحة المفاتيح
وتشغيله. لمعرفة المزيد حول هذين الموضوعَين، اطّلِع على مقالتَي ما هي إمكانات ARIA؟ واستخدام tabindex.
عند وضع علامة في مربّع الاختيار، تتم إضافة سمة منطقية checked
وضبط
سمة checked
المقابلة على true
. بالإضافة إلى ذلك، يضبط العنصر سمة
aria-checked
على "true"
أو "false"
، استنادًا إلى
حالته. يؤدي النقر على مربّع الاختيار باستخدام الماوس أو شريط المسافة إلى تبديل حالات الاختيار هذه.
يتيح مربّع الاختيار أيضًا حالة disabled
. إذا تم ضبط الخاصية disabled
على true أو تم تطبيق السمة disabled
، يضبط مربّع الاختيار
aria-disabled="true"
ويزيل السمة tabindex
ويعيد التركيز
إلى المستند إذا كان مربّع الاختيار هو activeElement
الحالي.
يتم إقران مربّع الاختيار بعنصر howto-label
لضمان أنّه يحتوي على
اسم متاح للاستخدام.
مَراجع
- كيفية استخدام المكوّنات على GitHub
- نمط مربّع الاختيار في ممارسات إنشاء ARIA 1.1
- ما هي الإجراءات التي يمكن لـ ARIA تنفيذها؟
- استخدام سمة tabindex
عرض توضيحي
الاطّلاع على العرض المباشر على GitHub
مثال على الاستخدام
<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>
الرمز
(function() {
حدِّد رموز المفاتيح للمساعدة في معالجة أحداث لوحة المفاتيح.
const KEYCODE = {
SPACE: 32,
};
إنّ استنساخ المحتوى من عنصر <template>
يحقّق أداءً أفضل من استخدام innerHTML لأنّه يتجنّب تكاليف إضافية لتحليل 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'];
}
يتم تشغيل أسلوب الإنشاء للعنصر في أي وقت يتم فيه إنشاء مثيل جديد. يتم إنشاء النُسخ عن طريق تحليل HTML أو استدعاء document.createElement('howto-checkbox') أو استدعاء new HowToCheckbox();. إنّ المُنشئ هو مكان جيد لإنشاء DOM الظل، ولكن عليك تجنُّب لمس أي سمات أو عناصر DOM الخفيفة لأنّها قد لا تكون متاحة بعد.
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
يتم تنشيط connectedCallback()
عند إدراج العنصر في DOM. وهو مكان مناسب لضبط أدوات معالجة الأحداث المبدئية في role
وtabindex
والحالة الداخلية وعمليات التثبيت.
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
يمكن للمستخدم ضبط خاصيّة في مثيل عنصر قبل ربط نموذجه الأولي بهذه الفئة. ستتحقّق الطريقة _upgradeProperty()
من توفُّر أي سمات مثيل وستشغّلها من خلال أدوات تحديد الفئة المناسبة. راجِع قسم الخصائص غير المُشغَّلة للحصول على مزيد من التفاصيل.
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()
عند إزالة العنصر من واجهة DOM. إنه مكان جيد لإنجاز الأعمال مثل إصدار المراجع وإزالة المستمعين للأحداث.
disconnectedCallback() {
this.removeEventListener('keyup', this._onKeyUp);
this.removeEventListener('click', this._onClick);
}
يجب أن تتطابق السمات مع الخصائص المقابلة لها. يعالج مُعدِّل السمة checked القيم الصحيحة/الخاطئة ويعكسها في حالة السمة. راجِع قسم تجنُّب إعادة الدخول للحصول على مزيد من التفاصيل.
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()
عند تغيير أيّ من السمات في صفيف observedAttributes. وهو مكان جيد للتعامل مع الآثار الجانبية، مثل ضبط سمات 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);
لا توفّر السمة tabindex
طريقة لإزالة إمكانية التركيز على عنصر بالكامل. سيظلّ بإمكانك التركيز على العناصر التي تتضمّن tabindex=-1
باستخدام الماوس أو من خلال طلب القيمة focus()
. للتأكّد من أنّ العنصر غير مفعّل ولا يمكن التركيز عليه، أزِل السمة tabindex
.
if (hasValue) {
this.removeAttribute('tabindex');
إذا كان التركيز حاليًا على هذا العنصر، أزِل التركيز منه من خلال استدعاء الطريقة HTMLElement.blur()
.
this.blur();
} else {
this.setAttribute('tabindex', '0');
}
break;
}
}
_onKeyUp(event) {
لا تتعامل مع اختصارات المُعدِّلات التي تستخدمها عادةً التكنولوجيا المساعِدة.
if (event.altKey)
return;
switch (event.keyCode) {
case KEYCODE.SPACE:
event.preventDefault();
this._toggleChecked();
break;
ويتم تجاهل أي ضغطة مفتاحية أخرى وإعادتها إلى المتصفِّح.
default:
return;
}
}
_onClick(event) {
this._toggleChecked();
}
يُطلِق _toggleChecked()
طريقة الضبط checked ويغيّر حالتها. وبما أنّ الحدث _toggleChecked()
لا يحدث إلا نتيجة إجراء يتّخذه المستخدِم، سيتم أيضًا إرسال حدث تغيير. يتم تجميع هذا الحدث لمحاكاة السلوك الأصلي لـ <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);
})();