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

<howto-checkbox>, formdaki bir 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 ekleyerek klavyeyle odaklanabilir ve kullanılabilir 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 bir checked boole özelliği eklenir ve ilgili checked özelliği true olarak ayarlanır. Ayrıca öğe, durumuna bağlı olarak aria-checked özelliğini "true" veya "false" olarak ayarlar. Onay kutusunu fareyle veya boşluk tuşuyla tıkladığınızda bu onaylanmış 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 kutusu, erişilebilir bir ada sahip olması için bir howto-label öğesiyle eşleştirilir.

Referans

Demo

Canlı demoyu GitHub'da görüntüleme

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

<template> öğesindeki içeriklerin klonlanması, ek HTML ayrıştırma maliyetlerini önlediği için innerHTML kullanmaktan daha yüksek performanslıdır.

  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, tüm örnek özelliklerini kontrol eder ve bunları uygun sınıf ayarlayıcıları üzerinden ç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);
    }

Tesisler ve ilgili özellikleri birbirini yansıtmalıdır. checked özelliğinin ayarlayıcısı, 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 tüm tuş basımları yoksayılır ve tarayıcıya geri iletilir.

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