Adobe-Consulting-Services/acs-aem-commons

View on GitHub
ui.apps/src/main/content/jcr_root/apps/acs-commons/authoring/granite-select-filter/granite-select-filter.js

Summary

Maintainability
A
0 mins
Test Coverage
(function(){

  // new coral text field to be use as filter input
  function newFilterTextField() {
    var filter = new Coral.Textfield();
    filter.classList.add("coral-Form-field");
    filter.placeholder = "filter";
    return filter;
  }

  /**
   * validates some assumptions about the select element structure:
   *  1. it must have a coral-overlay child.
   *  2. coral-overlay must have a coral-selectlist child.
   *  3. coral-selectlist must have items.
   */
  function isValidSelectDomStruture(selectEl) {
    var overlay = selectEl.querySelector("coral-overlay");
    var selectList = overlay ? overlay.querySelector("coral-selectlist") : null;
    var items = selectList ? selectList.items : false;
    // coral-overlay must exist & coral-selectlist must exist & coral-selectlist must have items.
    return !!overlay && !!selectList && !!items;
  }

  /**
   * Hides all items on the selectListEl that do not conatain the filterText, ignoring case.
   * @param {*} selectListEl the "coral-selectlist" element.
   * @param {*} filterText the search string (filter).
   */
  function filterSelectList(selectListEl, filterText) {
    selectListEl.items.getAll().forEach(function (item) {
      var itemText = item.textContent;
      var bothNotEmpty = itemText && filterText;
      var match =
        bothNotEmpty &&
        itemText.toLowerCase().indexOf(filterText.toLowerCase()) > -1;
      var eitherIsEmpty = !itemText || !filterText;
      if (eitherIsEmpty || match) {
        item.show();
      } else {
        item.hide();
      }
    });
  }

  var ATTR_FILTER_READY = "data-select-filter-ready";
  /**
   * Initialize filter on the passed select element.
   */
  function initFilter(selectEl) {
    if (selectEl.hasAttribute(ATTR_FILTER_READY)) {
      return; // exit, already initialized.
    } else {
      selectEl.setAttribute(ATTR_FILTER_READY, "true");
    }
    // exit here if structure does not match our assumptions
    if (!isValidSelectDomStruture(selectEl)) {
      console.info(
        "Could not add select filter to the following coral select element. It does not follow the specified structure",
        selectEl
      );
      return;
    }
    var filter = newFilterTextField();
    var overlay = selectEl.querySelector("coral-overlay");
    var selectList = overlay.querySelector("coral-selectlist");
    // add the filter field to the beginning of the list
    selectList.items.add(filter, selectList.items.first());
    // apply filter on keyup
    filter.addEventListener("keyup", function() {
      var filterValue = filter.value;
      filterSelectList(selectList, filterValue);
    });
  }

  // listen for component initialization (AEM component dialogs or otherwise)
  $(document).on("foundation-contentloaded", function(e) {
    var container = e.target;
    $("coral-select", container)
    .filter("[data-acs-select-filter]") // only elements with attribute data-acs-select-filter
    .each(function (i, el) {
      Coral.commons.ready(el, function(selectEl) {
        initFilter(selectEl);
      });
    });
  });
})();