"Nasıl Yapılır?" Bileşenleri – "nasıl yapılır" onay kutusu

Özet

<howto-checkbox>, bir formdaki Boole seçeneğini temsil eder. En yaygın onay kutusu türü, kullanıcının işaretli ve işaretsiz olmak üzere iki seçenek arasında geçiş yapmasına olanak tanıyan çift türdür.

Öğe, ilk oluşturulduğunda role="checkbox" ve tabindex="0" özelliklerini uygulamaya çalışır. role özelliği, ekran okuyucu gibi yardımcı teknolojilerin kullanıcıya bunun ne tür bir kontrol olduğunu söylemesine yardımcı olur. tabindex özelliği, öğeyi sekme sırasına dahil ederek klavyeye odaklanılabilir ve çalışabilir hale getirir. Bu iki konu hakkında daha fazla bilgi edinmek için ARIA neler yapabilir? ve Sekme Dizinini kullanma sayfalarına göz atın.

Onay kutusu işaretlendiğinde, bir checked boole özelliği ekler ve karşılık gelen checked özelliğini true olarak ayarlar. Ayrıca, öğe, durumuna bağlı olarak bir aria-checked özelliğini "true" veya "false" değerine ayarlar. Fare veya boşluk çubuğuyla onay kutusunu tıklamak, bu işaretli durumları açıp kapatır.

Onay kutusu, disabled durumunu da destekler. disabled özelliği true olarak ayarlanırsa veya disabled özelliği uygulanırsa onay kutusu aria-disabled="true" özelliğini ayarlar, tabindex özelliğini kaldırır ve onay kutusu geçerli activeElement ise odağı dokümana döndürür.

Onay kutusu, erişilebilir bir ada sahip olduğundan emin olmak için bir howto-label öğesiyle eşlenir.

Referans

Demo

GitHub'da canlı demoyu görüntüleyin

Örnek kullanım

<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>

Kod

(function() {

Klavye etkinliklerinin işlenmesine yardımcı olacak tuş kodlarını tanımlayın.

  const KEYCODE = {
    SPACE: 32,
  };

<template> öğesinden içerik klonlamak, ek HTML ayrıştırma maliyetlerinin önlenmesi için nerHTML'yi kullanmaktan daha etkilidir.

  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'];
    }

Öğenin oluşturucusu, yeni bir örnek oluşturulduğunda çalıştırılır. Örnekler HTML ayrıştırma, document.createElement('howto-checkbox') çağrılması veya yeni HowToCheckbox() çağrısı yapılarak oluşturulur. Oluşturucu, gölge DOM'u oluşturmak için iyi bir yerdir; ancak, henüz kullanılabilir olmayabilecek özelliklere veya ışık DOM alt öğelerine dokunmaktan kaçınmanız gerekir.

    constructor() {
      super();
      this.attachShadow({mode: 'open'});
      this.shadowRoot.appendChild(template.content.cloneNode(true));
    }

Öğe DOM'ye eklendiğinde connectedCallback() tetiklenir. Başlangıç role, tabindex, dahili durum ve yükleme etkinliği işleyicilerini ayarlamak için iyi bir yerdir.

    connectedCallback() {
      if (!this.hasAttribute('role'))
        this.setAttribute('role', 'checkbox');
      if (!this.hasAttribute('tabindex'))
        this.setAttribute('tabindex', 0);

Kullanıcı, prototipi bu sınıfa bağlanmadan önce bir öğenin örneğinde bir özellik ayarlayabilir. _upgradeProperty() yöntemi, örnek özelliklerini kontrol eder ve bunları uygun sınıf belirleyiciler üzerinden çalıştırır. Daha ayrıntılı bilgi için geç özellikler bölümüne bakın.

      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;
      }
    }

Öğe DOM'den kaldırıldığında disconnectedCallback() tetiklenir. Referans yayınlama ve etkinlik dinleyicilerini kaldırma gibi işleri temizlemek için iyi bir yerdir.

    disconnectedCallback() {
      this.removeEventListener('keyup', this._onKeyUp);
      this.removeEventListener('click', this._onClick);
    }

Özellikler ve karşılık gelen özellikleri birbirini yansıtmalıdır. İşaretlenen özellik ayarlayıcı, doğru/yanlış değerleri işler ve bunları özelliğin durumuna yansıtır. Daha ayrıntılı bilgi için tekrar girmeme bölümüne bakın.

    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');
    }

Gözlem Özellikleri dizisindeki özelliklerden herhangi biri değiştirildiğinde attributeChangedCallback() çağrılır. Burası, ARIA özelliklerini ayarlama gibi yan etkilerle başa çıkmak için iyi bir yerdir.

    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 özelliği, bir öğenin odaklanılabilirliğini tamamen kaldırmanın bir yolunu sağlamaz. tabindex=-1 içeren öğelere bir imleçle veya focus() çağrısı yapılarak odaklanılabilir. Bir öğenin devre dışı bırakıldığından ve odaklanılamayacağından emin olmak için tabindex özelliğini kaldırın.

          if (hasValue) {
            this.removeAttribute('tabindex');

Odak şu anda bu öğedeyse HTMLElement.blur() yöntemini çağırarak odağı kaldırma

            this.blur();
          } else {
            this.setAttribute('tabindex', '0');
          }
          break;
      }
    }

    _onKeyUp(event) {

Genellikle yardımcı teknolojiler tarafından kullanılan değiştirici kısayolları kullanmayın.

      if (event.altKey)
        return;

      switch (event.keyCode) {
        case KEYCODE.SPACE:
          event.preventDefault();
          this._toggleChecked();
          break;

Basılan diğer tuşlar yoksayılır ve tarayıcıya geri verilir.

        default:
          return;
      }
    }

    _onClick(event) {
      this._toggleChecked();
    }

_toggleChecked(), işaretli setter aracını çağırır ve durumunu çevirir. _toggleChecked() yalnızca bir kullanıcı işleminden kaynaklandığından, bir değişiklik etkinliği de gönderir. Bu etkinlik, <input type=checkbox> uygulamasının yerel davranışını taklit etmek için baloncuk olarak gösterilir.

    _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);
})();