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

Özet

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

Öğe, ilk oluşturulduğunda role="checkbox" ve tabindex="0" özelliklerini kendi kendine 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 alarak klavyede odaklanılabilir ve çalışabilir hale getirir. Bu iki konu hakkında daha fazla bilgi edinmek için ARIA ne yapabilir? ve tabindex kullanma başlıklı makaleleri inceleyin.

Onay kutusu işaretlendiğinde checked boole özelliği eklenir ve true öğesine karşılık gelen checked özelliği ayarlanır. Buna ek olarak, öğe, bir aria-checked özelliğini durumuna bağlı olarak "true" veya "false" değerine ayarlar. Onay kutusunu fareyle veya boşluk tuşuyla tıkladığınızda bu işaretli durumlar açılıp kapanır.

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

Onay kutusunun erişilebilir bir ada sahip olması için howto-label öğesiyle eşleştirilmesi gerekir.

Referans

Demo

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

Ö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 etkinliklerini işlemeye yardımcı olması için tuş kodlarını tanımlayın.

  const KEYCODE = {
    SPACE: 32,
  };

Bir <template> öğesinden içerik klonlamak, ek HTML ayrıştırma maliyetlerini önlemesi nedeniyle innerHTML 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 kurucusu, yeni bir örnek oluşturulduğunda her zaman çalıştırılır. Örnekler, HTML ayrıştırılarak, document.createElement("howto-checkbox") çağrılarak veya new HowToCheckbox(); çağrılarak oluşturulur. Oluşturucu, gölge DOM oluşturmak için iyi bir yerdir ancak henüz kullanılamayabilecek özellikler veya hafif DOM alt öğelerine dokunmaktan kaçınmanız gerekir.

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

connectedCallback(), öğe DOM'ye eklendiğinde tetiklenir. İlk role, tabindex, dahili durumu ayarlamak ve etkinlik dinleyicileri yüklemek 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 aracılığıyla çalıştırır. Daha fazla bilgi için tembel mülkler 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;
      }
    }

disconnectedCallback(), öğe DOM'dan kaldırıldığında tetiklenir. Referansları serbest bırakma ve etkinlik dinleyicilerini kaldırma gibi temizleme işlemlerini yapmak için iyi bir yerdir.

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

Özellikler ve karşılık gelen özellikler birbirini yansıtmalıdır. İşaretlenmiş için özellik belirleyici, doğru/yanlış değerleri işler ve bunları özelliğin durumuna yansıtır. Daha fazla bilgi için yeniden girişten kaçınma 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');
    }

observedAttributes dizisindeki özelliklerden herhangi biri değiştiğinde attributeChangedCallback() çağrılır. ARIA özelliklerini ayarlama gibi yan etkileri ele almak 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 öğeler, fareyle veya focus() çağrılarak odaklanmaya devam edebilir. Bir öğenin devre dışı olduğundan ve odaklanılabilir olmadığı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ğını kaldırın.

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

    _onKeyUp(event) {

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

      if (event.altKey)
        return;

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

Diğer tuşlara basmalar yoksayılır ve tarayıcıya geri döner.

        default:
          return;
      }
    }

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

_toggleChecked(), checked ayarlayıcısını çağırır ve durumunu değiştirir. _toggleChecked() yalnızca bir kullanıcı işlemi nedeniyle gerçekleştiğinden bir değişiklik etkinliği de gönderilir. Bu etkinlik, <input type=checkbox>'ün doğal davranışını taklit etmek için oluşturulur.

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