کامپوننت های HowTo – جعبه چک نحوه انتخاب

خلاصه

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

مثال استفاده

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

ویژگی ها و ویژگی های مربوط به آنها باید منعکس کننده یکدیگر باشند. تنظیم‌کننده ویژگی برای علامت‌گذاری شده، مقادیر درستی/نادرستی را کنترل می‌کند و آن‌ها را به وضعیت ویژگی منعکس می‌کند. برای جزئیات بیشتر به بخش اجتناب از ورود مجدد مراجعه کنید.

    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() تنظیم کننده علامت زده شده را فراخوانی می کند و وضعیت آن را تغییر می دهد. از آنجایی که _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);
})();