สรุป
<howto-checkbox> แสดงตัวเลือกบูลีนในแบบฟอร์ม ช่องทําเครื่องหมายประเภทที่พบบ่อยที่สุดคือประเภทคู่ ซึ่งช่วยให้ผู้ใช้สลับระหว่างตัวเลือก 2 รายการ ได้แก่ เลือกและยกเลิกการเลือก
องค์ประกอบจะพยายามใช้แอตทริบิวต์ role="checkbox" และ tabindex="0" ด้วยตนเองเมื่อสร้างเป็นครั้งแรก แอตทริบิวต์ role ช่วยให้เทคโนโลยีความช่วยเหลือพิเศษ เช่น โปรแกรมอ่านหน้าจอ บอกผู้ใช้ได้ว่าการควบคุมประเภทนี้เป็นประเภทใด ส่วนแอตทริบิวต์ tabindex จะเลือกองค์ประกอบให้อยู่ในลําดับการกด Tab ซึ่งทําให้โฟกัสและใช้งานด้วยแป้นพิมพ์ได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับ 2 หัวข้อนี้ได้ที่หัวข้อARIA ทำอะไรได้บ้างและการใช้ tabindex
เมื่อเลือกช่องทําเครื่องหมาย ระบบจะเพิ่มแอตทริบิวต์บูลีน checked และตั้งค่าพร็อพเพอร์ตี้ checked ที่เกี่ยวข้องเป็น true นอกจากนี้ องค์ประกอบจะตั้งค่าแอตทริบิวต์ aria-checked เป็น "true" หรือ "false" ทั้งนี้ขึ้นอยู่กับสถานะ การคลิกช่องทําเครื่องหมายด้วยเมาส์หรือแป้นเว้นวรรคจะสลับสถานะ "เลือกแล้ว" เหล่านี้
ช่องทําเครื่องหมายยังรองรับสถานะ disabled ด้วย หากตั้งค่าพร็อพเพอร์ตี้ disabled เป็น "จริง" หรือใช้แอตทริบิวต์ disabled ช่องทำเครื่องหมายจะตั้งค่า aria-disabled="true" นำแอตทริบิวต์ tabindex ออก และคืนค่าโฟกัสไปยังเอกสารหากช่องทำเครื่องหมายเป็น activeElement ในปัจจุบัน
ช่องทำเครื่องหมายจะจับคู่กับองค์ประกอบ howto-label เพื่อให้มีชื่อที่เข้าถึงได้
ข้อมูลอ้างอิง
- วิธีการ: คอมโพเนนต์ใน GitHub
- รูปแบบช่องทำเครื่องหมายใน ARIA Authoring Practices 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(); ตัวสร้างคอนสตรัคเตอร์เป็นตําแหน่งที่ดีในการสร้าง Shadow DOM แต่คุณควรหลีกเลี่ยงการแตะแอตทริบิวต์หรือ DOM ย่อยของ Light เนื่องจากอาจยังไม่พร้อมใช้งาน
    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);
})();
 
 
        
        