チェックボックス(トライステート)

チェックボックス(トライステート)

トライステートチェックボックスは、チェックされている、チェックされていない、または部分的にチェックされている状態にすることができます。部分的にチェックされる条件は、子要素の選択に基づきます。すべての子要素が選択されている場合、親のチェックボックスがチェックされます。一部の子要素が選択されている場合、親のチェックボックスは部分的にチェックされます。



スクリーンリーダーをオンにして、この例を実際に体験してください。

Choose the ingredients for your pizza.
Select all ingredients
Cheese
Mushrooms
Olives

初期HTMLマークアップ

すべてのチェックボックストライステートグループには、何らかのグループラベルが必要です。従来の方法は <fieldset> と を使用するです<legend>。ARIAの方法も role="checkbox"aria-labelledby で使用できます。

方法1: <fieldset><legend>

<fieldset class="deque-checkbox-tristate-group">
<legend class="deque-checkbox-group-label">Choose the ingredients for your pizza.</legend>
  <div class = "deque-checkbox-tristate-parent">
    <div>
      <span class="deque-checkbox-tristate" aria-labelledby="all-ingredients"></span>
      <span id="all-ingredients">Select all ingredients</span>
    </div>
  </div>
  <div class="deque-checkbox-tristate-children">
    <div>
      <span class="deque-checkbox-tristate" aria-labelledby="cheese"></span>
      <span id="cheese">Cheese</span>
    </div>
    <div>
      <span class="deque-checkbox-tristate" aria-labelledby="mushrooms"></span>
      <span id="mushrooms">Mushrooms</span>
    </div>
    <div>
      <span class="deque-checkbox-tristate" aria-labelledby="olives"></span>
      <span id="olives">Olives</span>
    </div>
  </div>
</fieldset>

方法2: role="checkbox"aria-labelledby

<div class="custom-checkbox-widget" data-group-title="Choose the toppings for your ice cream" data-group-option-title="Select all toppings" data-delimiter="--" data-options="Oreos, Gems -- Gummy Bears --Strawberries"></div>

<div class="custom-checkbox-widget" data-group-title="Choose Operating Systems" data-group-option-title="Select all Operating Systems" data-options="Windows, Linux, MacOS"></div>

JavaScript

必須: 完全なJavaScriptファイル(ライブラリ内のすべてのパターン用): deque-patterns.min.js

JavaScriptファイルの主要部分

注: 以下のコードは、完全なJavaScriptファイルのコンテキストでのみ機能します。

@checkboxセクション:


      /*
    	
      TO DO:
    	
      - Throw an error if the label is missing
      */

      function toggle(element) {
        if (isToggledOn(element)) {
          toggleOff(element);
        } else {
          toggleOn(element);
        }
      }

      function isToggledOn(element) {
        return getCheckboxData(element) === 'true';
      }

      function replaceSpace(str) {
        return str.replace(/ /g, '_').toLowerCase();
      }

      function buildCheckboxTristate() {
        var _customCheckboxTristateWidgets = document.querySelectorAll('.custom-checkbox-widget');
        var _instanceChkTristateCount = 0;
        if (_customCheckboxTristateWidgets.length > 0) {
          [].slice.call(_customCheckboxTristateWidgets).forEach(function (_eachCustomWidget) {
            var _dataConfig = {
              groupTitle: _eachCustomWidget.getAttribute('data-group-title'),
              groupOptionTitle: _eachCustomWidget.getAttribute('data-group-option-title'),
              options: _eachCustomWidget.getAttribute('data-options'),
              delimiter: _eachCustomWidget.getAttribute('data-delimiter') || ','
            };

            if (_dataConfig.options) {
              _dataConfig.options = _dataConfig.options.split(_dataConfig.delimiter);
            }

            var _id = 'instance_' + _instanceChkTristateCount + '_' + replaceSpace(_dataConfig.groupTitle);

            var _elementControl = '<div class="custom-checkbox" id="' + _id + '" role="group" aria-labelledby="group-header' + _id + '">';
            _elementControl += '<div class="checkbox-group-heading" id="group-header' + _id + '">' + _dataConfig.groupTitle + '</div>';
            _elementControl += '<div role="checkbox" name="parent-checkbox[]" data-childs="' + _id + '_childs" class="parent-checkbox checkbox-holder" \
	                                              aria-labelledby="' + _id + replaceSpace(_dataConfig.groupOptionTitle) + '" tabindex="0"> \
	                                              <span class="checkbox-indicator"></span> \
	                                              <span class="checkbox-label" id="' + _id + replaceSpace(_dataConfig.groupOptionTitle) + '">' + _dataConfig.groupOptionTitle + '</span> \
	                                          </div> \
	                                          <div class="child-checkbox-list" data-group="' + _id + '">';

            for (var _elementOptionIndex in _dataConfig.options) {
              _elementControl += '<div role="checkbox" name="child-checkbox[]" class="child-checkbox checkbox-holder ' + _id + '_childs" aria-labelledby="' + _id + replaceSpace(_dataConfig.options[_elementOptionIndex]) + '" tabindex="0"> \
	                                                  <span class="checkbox-indicator"></span> \
	                                                  <span class="checkbox-label" id="' + _id + replaceSpace(_dataConfig.options[_elementOptionIndex]) + '">' + _dataConfig.options[_elementOptionIndex] + '</span> \
	                                              </div>';
            }

            _elementControl += '</div></div>';

            _eachCustomWidget.innerHTML = _elementControl;
            _instanceChkTristateCount++;
          });

          var parentCheckboxElements = document.querySelectorAll('.parent-checkbox');
          [].slice.call(parentCheckboxElements).forEach(function (eachParent) {
            eachParent.addEventListener('click', checkboxEvent);
            eachParent.addEventListener('keyup', checkboxEvent);
          });
          var childElements = document.querySelectorAll('.child-checkbox');
          [].slice.call(childElements).forEach(function (eachChildElement) {
            eachChildElement.addEventListener('click', checkboxEvent);
            eachChildElement.addEventListener('keyup', checkboxEvent);
          });
        }
      }

      buildCheckboxTristate();

      function checkboxEvent(event) {
        if (event.keyCode == 13 || event.keyCode == 32 || !event.keyCode) {
          var element = event.currentTarget;
          if (element.getAttribute('aria-checked') == 'true') {
            element.setAttribute('aria-checked', 'false');
            element.classList.remove('active');
          } else {
            element.setAttribute('aria-checked', 'true');
            element.classList.add('active');
          }

          if (element.getAttribute('data-childs')) {
            var childElements = document.querySelectorAll('.' + element.getAttribute('data-childs'));
            [].slice.call(childElements).forEach(function (eachChildElement) {
              if (element.classList.contains('parent-checkbox')) {
                eachChildElement.setAttribute('aria-checked', element.getAttribute('aria-checked'));
              }
            });
          }

          var parentElement = document.querySelector('#' + element.parentElement.getAttribute('data-group'));
          if (parentElement) {
            var innerParent = parentElement.querySelector('.parent-checkbox');
            if (innerParent) {
              var checkboxCounter = parentElement.querySelectorAll('.child-checkbox[aria-checked="true"]').length;
              var _childElements = parentElement.querySelectorAll('.child-checkbox');
              if (checkboxCounter == 0) {
                innerParent.setAttribute('aria-checked', 'false');
              } else if (checkboxCounter < _childElements.length) {
                innerParent.setAttribute('aria-checked', 'mixed');
              } else if (checkboxCounter == _childElements.length) {
                innerParent.setAttribute('aria-checked', 'true');
              }
            }
          }
        }
      }

      function setCheckboxData(element, value) {
        element.setAttribute('aria-checked', value);
        var dataElement = document.getElementById('checkboxTristateData[' + element.getAttribute('aria-labelledby') + ']');
        if (dataElement) dataElement.value = value;
      }

      function getCheckboxData(element) {
        var dataElement = document.getElementById('checkboxTristateData[' + element.getAttribute('aria-labelledby') + ']');
        return dataElement ? dataElement.value : null;
      }

      function toggleOn(element) {
        setCheckboxData(element, 'true');
      }

      function toggleOff(element) {
        setCheckboxData(element, 'false');
      }

      function toggleMixed(element) {
        setCheckboxData(element, 'mixed');
      }
      function createSingleCheckbox(checkbox, isChecked) {
        var onChange = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () { };

        checkbox.setAttribute('tabindex', '0');
        checkbox.setAttribute('role', 'checkbox');
        var indicator = document.createElement('span');
        indicator.classList.add('deque-checkbox-indicator');

        checkbox.appendChild(indicator);

        var labelText = checkbox.getAttribute('aria-labelledby');
        var label = document.getElementById(labelText);
        //label.setAttribute('aria-hidden', 'true'); // prevents double readout
        label.classList.add('deque-checkbox-label');

        var hiddenCheckbox = document.createElement('input');
        hiddenCheckbox.type = 'hidden';
        hiddenCheckbox.name = 'checkboxTristateData[' + labelText + ']';
        hiddenCheckbox.id = 'checkboxTristateData[' + labelText + ']';
        hiddenCheckbox.classList.add('deque-checkbox-data');

        checkbox.appendChild(hiddenCheckbox);

        /*checkbox.addEventListener('focus', function () {
          var allCheckboxElements = document.querySelectorAll('.deque-checkbox-tristate-parent');
          [].slice.call(allCheckboxElements).forEach(element => {
            element.setAttribute('aria-hidden', 'true');
          });
        });*/

        if (isChecked) {
          toggleOn(checkbox);
        } else {
          toggleOff(checkbox);
        }

        function changeHandler(e) {
          e.stopPropagation();
          e.preventDefault();
          toggle(checkbox);
          broadcastChange();
        }

        function broadcastChange() {
          onChange({ element: checkbox, isToggledOn: isToggledOn(label) });
        }

        checkbox.parentNode.addEventListener('click', changeHandler);
        (0, _keyboardUtils.onElementSpace)(checkbox, changeHandler);
        (0, _keyboardUtils.onElementEnter)(checkbox, changeHandler);

        checkbox.parentNode.addEventListener('focus', function () {
          checkbox.classList.add('deque-checkbox-focused');
        });

        checkbox.parentNode.addEventListener('blur', function () {
          checkbox.classList.remove('deque-checkbox-focused');
        });

        return checkbox;
      }

      function createSingleCheckboxForRadio(checkbox, checkboxLabel, isChecked) {
        var onChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () { };


        checkbox.setAttribute('tabindex', '0');
        checkbox.setAttribute('role', 'checkbox');

        var indicator = document.createElement('span');
        indicator.classList.add('deque-checkbox-indicator');

        checkbox.appendChild(indicator);

        var labelText = checkbox.getAttribute('aria-labelledby');
        var label = document.getElementById(labelText);
        //label.setAttribute('aria-hidden', 'true'); // prevents double readout
        label.classList.add('deque-checkbox-label');

        var hiddenRadio = document.createElement('input');
        hiddenRadio.type = 'hidden';
        hiddenRadio.name = 'checkboxTristateData[' + labelText + ']';
        hiddenRadio.id = 'checkboxTristateData[' + labelText + ']';
        hiddenRadio.classList.add('deque-checkbox-radio-data');
        checkbox.appendChild(hiddenRadio);
        checkbox.appendChild(label);

        if (isChecked) {
          toggleOn(checkbox);
        } else {
          toggleOff(checkbox);
        }

        function changeHandler(e) {
          e.stopPropagation();
          e.preventDefault();
          toggle(checkbox);
          broadcastChange();
        }

        function broadcastChange() {
          onChange({ element: checkbox, isToggledOn: isToggledOn(label) });
        }

        checkbox.addEventListener('click', changeHandler);
        checkbox.addEventListener('keydown', changeHandler);

        checkboxLabel.addEventListener('click', changeHandler);
        (0, _keyboardUtils.onElementSpace)(checkbox, changeHandler);

        checkbox.addEventListener('focus', function () {
          checkbox.classList.add('deque-radio-focused');
        });

        checkbox.addEventListener('blur', function () {
          checkbox.classList.remove('deque-radio-focused');
        });

        return checkbox;
      }

      function createCheckboxGroup(parent, children) {
        var onChange = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () { };


        parent = createSingleCheckbox(parent, false, function (e) {
          onChange(e);
          rootClicked(getCorrectRootState());
        });

        children = Array.prototype.slice.call(children);

        children = children.map(function (child) {
          return createSingleCheckbox(child, false, function () {
            if (onChange) {
              onChange(child);
            }
            setCorrectRootState();
          });
        });

        var rootClickHandlers = {
          'true': function _true() {
            children.forEach(toggleOff);
            toggleOff(parent);
          },
          'false': function _false() {
            children.forEach(toggleOn);
            toggleOn(parent);
          },
          'mixed': function mixed() {
            children.forEach(toggleOn);
            toggleOn(parent);
          }
        };

        function rootClicked(rootState) {
          rootClickHandlers[rootState]();
        }

        function getCorrectRootState() {
          if (children.every(isToggledOn)) {
            return 'true';
          } else if (children.every(function (child) {
            return !isToggledOn(child);
          })) {
            return 'false';
          } else {
            return 'mixed';
          }
        }

        var leafClickHandlers = {
          'true': function _true() {
            return toggleOn(parent);
          },
          'false': function _false() {
            return toggleOff(parent);
          },
          'mixed': function mixed() {
            return toggleMixed(parent);
          }
        };

        function setCorrectRootState() {
          leafClickHandlers[getCorrectRootState()]();
        }
      }

      function activateAllCheckboxes() {
        var checkboxes = document.querySelectorAll('.deque-checkbox-aria');
        for (var i = 0; i < checkboxes.length; i++) {
          var childNode = checkboxes[i].querySelector('.deque-checkbox-data');
          if (!checkboxes[i].contains(childNode)) {
            createSingleCheckbox(checkboxes[i], false);
          }
        }

        var tristates = document.querySelectorAll('.deque-checkbox-tristate-group');
        for (var j = 0; j < tristates.length; j++) {
          var parentGroup = tristates[j].querySelector('.deque-checkbox-tristate-parent');
          var parent = parentGroup.querySelector('.deque-checkbox-tristate');
          var childrenGroup = tristates[j].querySelector('.deque-checkbox-tristate-children');
          var children = childrenGroup.querySelectorAll('.deque-checkbox-tristate');
          childNode = childrenGroup.querySelector('.deque-checkbox-data');
          if (!childrenGroup.contains(childNode)) {
            createCheckboxGroup(parent, children);
          }
        }
      }

      activateAllCheckboxes();

      

@keyboardUtilsセクションで:


      var KEYS = exports.KEYS = {
        BACKSPACE: 8,
        TAB: 9,
        ENTER: 13,
        SHIFT: 16,
        CTRL: 17,
        ALT: 18,
        ESCAPE: 27,
        SPACE: 32,
        LEFT: 37,
        RIGHT: 39,
        UP: 38,
        DOWN: 40,
        F10: 121,
        HOME: 36,
        END: 35,
        PAGE_UP: 33,
        PAGE_DOWN: 34
      };

      function bindElementToEventValue(element, eventName, testValue, handler) {
        function localHandler(e) {
          if (e.which === testValue) {
            handler(e);
          }
        }

        element.addEventListener(eventName, localHandler);
        return function () {
          element.removeEventListener(eventName, localHandler);
        };
      }

      function bindElementToKeypressValue(element, testValue, handler) {
        return bindElementToEventValue(element, 'keypress', testValue, handler);
      }

      function bindElementToKeydownValue(element, testValue, handler) {
        return bindElementToEventValue(element, 'keydown', testValue, handler);
      }

      function onElementEnter(element, handler) {
        return bindElementToKeydownValue(element, KEYS.ENTER, handler);
      }

      function onElementEscape(element, handler) {
        return bindElementToKeydownValue(element, KEYS.ESCAPE, handler);
      }

      function onElementSpace(element, handler) {
        return bindElementToKeypressValue(element, KEYS.SPACE, handler);
      }

      function onElementLeft(element, handler) {
        return bindElementToKeydownValue(element, KEYS.LEFT, handler);
      }

      function onElementRight(element, handler) {
        return bindElementToKeydownValue(element, KEYS.RIGHT, handler);
      }

      function onElementUp(element, handler) {
        return bindElementToKeydownValue(element, KEYS.UP, handler);
      }

      function onElementDown(element, handler) {
        return bindElementToKeydownValue(element, KEYS.DOWN, handler);
      }

      function onElementHome(element, handler) {
        return bindElementToKeydownValue(element, KEYS.HOME, handler);
      }

      function onElementEnd(element, handler) {
        return bindElementToKeydownValue(element, KEYS.END, handler);
      }

      function onElementPageUp(element, handler) {
        return bindElementToKeydownValue(element, KEYS.PAGE_UP, handler);
      }

      function onElementPageDown(element, handler) {
        return bindElementToKeydownValue(element, KEYS.PAGE_DOWN, handler);
      }

      function onElementF10(element, handler) {
        return bindElementToKeydownValue(element, KEYS.F10, handler);
      }

      function isAlphaNumeric(charCode) {
        return charCode >= 48 && charCode <= 90 /* numbers, uppercase letters */
          || charCode >= 97 && charCode <= 122 /* lowercase letters */;
      }

      function onElementCharacter(element, handler) {
        function localHandler(e) {
          var charCode = e.which;
          if (isAlphaNumeric(charCode)) {
            handler(e);
          }
        }

        element.addEventListener('keypress', localHandler);
        return function () {
          element.removeEventListener('keypress', localHandler);
        };
      }

      function trapEnter(element) {
        onElementEnter(element, function (e) {
          e.stopPropagation();
          e.preventDefault();
        });
      }
      

@guidUtilsセクションで:


      /*
        note - not a true guid. I prepend 'g' because 
        the ID of an element cannot start with a numeral
      */

      function generateGuid() {
        var S4 = function S4() {
          return ((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1);
        };
        return 'g' + (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4());
      }
      

@containerUtilsセクションで:


      function elementIsChildOfElement(child, potentialParent) {
        while (child) {
          if (child === potentialParent) {
            return true;
          }

          child = child.parentNode;
        }

        return false;
      }

      function createFieldset(label) {
        var fieldset = document.createElement('fieldset');
        var legend = document.createElement('legend');
        legend.classList.add('legend'); // for easy lookup regardless of mode
        legend.id = (0, _guidUtils.generateGuid)();
        legend.innerText = label;
        fieldset.appendChild(legend);
        return fieldset;
      }

      function createLiveRegion() {
        var level = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'polite';
        var classes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

        var output = document.createElement('span');
        classes.forEach(function (c) {
          return output.classList.add(c);
        });
        output.id = (0, _guidUtils.generateGuid)();
        output.setAttribute('aria-live', level);
        output.classList.add('deque-visuallyhidden');
        output.innerText = '';
        output.notify = function (text) {
          // TODO: Clean this up...no need to extend the element prototype
          while (output.firstChild) {
            output.removeChild(output.firstChild);
          }
          var msg = document.createElement('div');
          msg.innerHTML = text;
          output.appendChild(msg);
        };

        return output;
      }
      

注: このパターンには、追加のJavaScript初期化コードは必要ありません。すべての要素はwith class="deque-checkbox-tristate-group" 、外部のJavaScriptファイルによって自動的に初期化されます。

CSS

必須: 完全なCSSファイル(ライブラリ内のすべてのパターン用): deque-patterns.min.css

CSSファイル内の主要なスタイル (他のスタイルも必要になる場合があります):


.deque-checkbox-label {
  vertical-align: middle;
  margin-left: 10px;
}
.deque-checkbox-label:hover {
  cursor: default;
}
.deque-checkbox-aria[role='checkbox'] {
  user-select: none;
}
.deque-checkbox-aria[role='checkbox'].deque-checkbox-focused {
  outline: none;
}
.deque-checkbox-aria[role='checkbox'].deque-checkbox-focused .deque-checkbox-indicator {
  outline: 1px dashed #000000;
}
.deque-checkbox-aria[role='checkbox'] .deque-checkbox-indicator {
  height: 20px;
  left: 0;
  width: 20px;
  line-height: 20px;
  box-shadow: inset 0 0 0 1px #000000, inset 0 0 0 10px transparent;
  top: 0;
  display: inline-block;
  position: relative;
  vertical-align: middle;
  border: 1px solid transparent;
}
.deque-checkbox-aria[role='checkbox'] .deque-checkbox-indicator:focus {
  outline: none;
  border: 1px dashed #000000;
}
.deque-checkbox-aria[role='checkbox'][aria-checked='true'] .deque-checkbox-indicator {
  box-shadow: inset 0 0 0 10px #0078d7;
}
.deque-checkbox-aria[role='checkbox'][aria-checked='true'] .deque-checkbox-indicator:after {
  content: '\E8FB';
  font-family: 'mwf-glyphs';
  color: #ffffff;
  font-size: 16px;
  padding-left: 2px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.deque-checkbox-aria[role='checkbox'][aria-checked='mixed'] .deque-checkbox-indicator {
  box-shadow: inset 0 0 0 10px #0078d7;
}
.deque-checkbox-aria[role='checkbox'][aria-checked='mixed'] .deque-checkbox-indicator:after {
  content: '\E738';
  font-family: 'mwf-glyphs';
  color: #ffffff;
  font-size: 16px;
  padding-left: 2px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.deque-checkbox-tristate-group {
  margin: 0;
  padding: 10px;
}
.deque-checkbox-tristate[role='checkbox'] {
  cursor: default;
  user-select: none;
}
.deque-checkbox-tristate[role='checkbox'].deque-checkbox-focused {
  outline: none;
}
.deque-checkbox-tristate[role='checkbox'].deque-checkbox-focused .deque-checkbox-indicator {
  outline: 1px dashed #000000;
}
.deque-checkbox-tristate[role='checkbox'] .deque-checkbox-indicator {
  height: 20px;
  left: 0;
  width: 20px;
  line-height: 20px;
  box-shadow: inset 0 0 0 1px #000000, inset 0 0 0 10px transparent;
  top: 0;
  display: inline-block;
  position: relative;
  vertical-align: middle;
  border: 1px solid transparent;
}
.deque-checkbox-tristate[role='checkbox'] .deque-checkbox-indicator:focus {
  outline: none;
  border: 1px dashed #000000;
}
.deque-checkbox-tristate[role='checkbox'][aria-checked='true'] .deque-checkbox-indicator {
  box-shadow: inset 0 0 0 10px #0078d7;
}
.deque-checkbox-tristate[role='checkbox'][aria-checked='true'] .deque-checkbox-indicator:after {
  content: '\E8FB';
  font-family: 'mwf-glyphs';
  color: #ffffff;
  font-size: 16px;
  padding-left: 2px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.deque-checkbox-tristate[role='checkbox'][aria-checked='mixed'] .deque-checkbox-indicator {
  box-shadow: inset 0 0 0 10px #0078d7;
}
.deque-checkbox-tristate[role='checkbox'][aria-checked='mixed'] .deque-checkbox-indicator:after {
  content: '\E738';
  font-family: 'mwf-glyphs';
  color: #ffffff;
  font-size: 16px;
  padding-left: 2px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.custom-checkbox-widget {
  margin: 20px 0px;
}
.custom-checkbox-widget .checkbox-group-heading {
  margin: 10px 0px;
}
.deque-checkbox-tristate-children {
  margin-left: 10px;
}
.custom-checkbox-widget .checkbox-holder .checkbox-indicator {
  height: 20px;
  width: 20px;
  border: 1px #000 solid;
  display: inline-block;
  margin-right: 12px;
}
.custom-checkbox-widget .checkbox-holder[aria-checked="true"] .checkbox-indicator {
  border: 1px #0078d7 solid;
}
.custom-checkbox-widget .checkbox-holder[aria-checked="mixed"] .checkbox-indicator {
  border: 1px #0078d7 solid;
}
.custom-checkbox-widget .checkbox-holder[aria-checked="true"] .checkbox-indicator,
.custom-checkbox-widget .checkbox-holder[aria-checked="mixed"] .checkbox-indicator {
  background: #0078d7;
  position: relative;
}
.custom-checkbox-widget .checkbox-holder[aria-checked="false"] .checkbox-indicator {
  background: none;
}
.custom-checkbox-widget .child-checkbox {
  margin-left: 16px;
}
.custom-checkbox-widget .checkbox-holder[aria-checked="true"] .checkbox-indicator::after {
  content: '\E8FB';
  font-family: mwf-glyphs;
  color: #fff;
  font-size: 16px;
  padding-left: 2px;
  position: absolute;
  top: -3px;
  left: 0;
  right: 0;
  bottom: 0;
}
.custom-checkbox-widget .checkbox-holder[aria-checked="mixed"] .checkbox-indicator::after {
  content: '\E738';
  font-family: mwf-glyphs;
  color: #fff;
  font-size: 16px;
  padding-left: 2px;
  position: absolute;
  top: -3px;
  left: 0;
  right: 0;
  bottom: 0;
}
.custom-checkbox-widget .checkbox-label {
  position: relative;
  top: -5px;
}

フォント

注: 外部CSSファイルの src のために font-family:'mwf-glyphs' を編集する必要があります。

実装手順

Step 1: Add Dependencies

Add deque-patterns.min.css in the <head> of the document.

<link rel="stylesheet" type="text/css" href="deque-patterns.min.css">

Add a script link to deque-patterns.min.js to the bottom of the page.

<script type="text/javascript" src="deque-patterns.min.js"></script>

Step 2: Add HTML

  • There are two different ways to organize the beginning of the HTML.
    • Method 1: This puts a box around your checkbox-tristate.
      • Create a <fieldset> container with class="deque-checkbox-tristate-group", for styling purposes and so the javascript can initialize each checkbox automatically.
      • Within the <fieldset> make a <legend> container with class="deque-checkbox-group-label". The inner text will be the title of this checkbox group.
    • Method 2:
      • Create a <div> container with following data-attributes
        • class="custom-checkbox-widget"
        • data-group-title="......"
        • data-group-option-title="......"
        • data-delimiter="--" (if not provided, default delimiter will be the comma(,))
        • data-options="a, b, c"
      • Values in the data-attributes will be dynamic / customized
  • Everything within these containers is the same.
    • The main checkbox is a <div> or <span> container with class="deque-checkbox-tristate-parent".
      • Within the parent container create a <div> or <span>.
        • Make a <div> or <span> with class="deque-checkbox-tristate" as well as the aria-labelledby attribute that corresponds with the checkbox's label ID. This container creates the box that becomes checked when selected.
        • Create another <div> or <span> with a unique ID. The inner text will be the content of the checkbox.
    • Then create the children group in a <div> or <span> container with class="deque-checkbox-tristate-children".
      • Within the children container create a <div> or <span>.
        • Make a <div> or <span> with class="deque-checkbox-tristate" as well as the aria-labelledby attribute that corresponds with the checkbox's label ID. This container creates the box that becomes checked when selected.
        • Create another <div> or <span> with a unique ID. The inner text will be the content of the checkbox.