HowTo कॉम्पोनेंट – कैसे करें-चेकबॉक्स

<howto-checkbox>, फ़ॉर्म में बूलियन विकल्प दिखाता है. चेकबॉक्स का सबसे आम टाइप, ड्यूअल-टाइप होता है. इसमें उपयोगकर्ता, सही का निशान लगाने और हटाने के बीच टॉगल कर सकता है.

एलिमेंट पहली बार बनने पर, role="checkbox" और tabindex="0" एट्रिब्यूट अपने-आप लागू होने की कोशिश करते हैं. role एट्रिब्यूट की मदद से, स्क्रीन रीडर जैसी सहायक टेक्नोलॉजी, उपयोगकर्ता को बताती है कि यह किस तरह का कंट्रोल है. tabindex एट्रिब्यूट, एलिमेंट को टैब ऑर्डर में शामिल करता है. इससे, कीबोर्ड से उस पर फ़ोकस किया जा सकता है और उसे इस्तेमाल किया जा सकता है. इन दोनों विषयों के बारे में ज़्यादा जानने के लिए, एआरआईए क्या कर सकता है? और tabindex का इस्तेमाल करना लेख पढ़ें.

चेकबॉक्स पर सही का निशान लगाने पर, यह checked बूलियन एट्रिब्यूट जोड़ता है. साथ ही, true में उससे जुड़ी checked प्रॉपर्टी सेट करता है. इसके अलावा, एलिमेंट अपनी स्थिति के आधार पर, aria-checked एट्रिब्यूट को "true" या "false" पर सेट करता है. माउस या स्पेस बार की मदद से चेकबॉक्स पर क्लिक करने पर, चुने गए इन राज्यों की स्थिति टॉगल हो जाती है.

चेकबॉक्स में disabled स्टेटस भी काम करता है. अगर disabled प्रॉपर्टी को 'सही है' पर सेट किया गया है या 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,
  };

innerHTML का इस्तेमाल करने के मुकाबले, <template> एलिमेंट से कॉन्टेंट को क्लोन करने की परफ़ॉर्मेंस बेहतर होती है. इसकी वजह यह है कि इससे एचटीएमएल को पार्स करने में लगने वाले समय की बचत होती है.

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

नया इंस्टेंस बनाए जाने पर एलिमेंट का कंस्ट्रक्टर चलाया जाता है. इंस्टेंस, एचटीएमएल को पार्स करके, 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(), एलिमेंट को डीओएम से हटाने पर ट्रिगर होता है. यह क्लीन अप करने के लिए एक अच्छी जगह है. जैसे, रेफ़रंस रिलीज़ करना और इवेंट के लिसनर हटाना.

    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() को तब कॉल किया जाता है, जब मॉनिटर किए गए एट्रिब्यूट के कलेक्शन में मौजूद किसी भी एट्रिब्यूट में बदलाव होता है. 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 setter को कॉल करता है और उसकी स्थिति बदल देता है. _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);
})();