module_builder-8.x-3.x-dev/js/component_form.autocomplete.js

js/component_form.autocomplete.js
/**
 * @file
 * Custom autocomplete for component forms.
 *
 * Autocomplete for textfields which supports:
 * - multiple lines per item, with match text and a description.
 * - links in the description which can be clicked without selecting the item.
 *
 * Data for the autocomplete is found int drupalSettings rather than retrieved
 * from a route.
 */

(function ($, Drupal, drupalSettings) {
  'use strict';

  /**
   * Holds all the list elements for the option sets.
   */
  var listElements = {};

  /**
   * Holds all the option elements, nested by option set name.
   */
  var optionElements = {};

  /**
   * Holds the strings to match, nested by option set name.
   */
  var optionSetTexts = {};

  Drupal.behaviors.moduleBuilderComponentAutocomplete = {
    attach: function (context, settings) {
      var $textField = $("input[data-option-set]");

      // Build the dropdowns and the option texts.
      jQuery.each(drupalSettings.moduleBuilder.options, function (optionSetName, optionSetValues) {
        // Skip if we've already created a UL element for this option set.
        if (optionSetName in listElements) {
          return;
        }

        listElements[optionSetName] = $("<ul class='module-builder-dropdown-list'></ul>");

        // Set the width to that of the textfields.
        listElements[optionSetName].width(
          $textField.width() +
          parseFloat($textField.css('padding-left')) +
          parseFloat($textField.css('padding-right'))
        );

        optionElements[optionSetName] = Array();
        optionSetTexts[optionSetName] = Array();

        jQuery.each(optionSetValues, function (optionKey, optionValue) {
          var optionHtml = '<li><p class="text">' + optionValue[0] + '</p>';
          if (optionValue[1]) {
            optionHtml += '<p class="form-item__description">' + optionValue[1] + '</p>';
          }
          if (optionValue[2]) {
            optionHtml += '<p class="form-item__description"><a target="_blank" href="' + optionValue[2] + '">[documentation]</a></p>';
          }
          optionHtml += '</li>';

          var newOption = $(optionHtml);
          listElements[optionSetName].append(newOption);

          optionElements[optionSetName].push(newOption);
          optionSetTexts[optionSetName].push(optionKey);

          // Clicking on an option (but not a link inside it) updates the
          // textfield.
          newOption.on('click', function (e) {
            if (e.target.nodeName == 'A') {
              return;
            }

            // Set the value of the text field.
            listElements[optionSetName].attached.value = optionKey;
            // Hide the dropdown.
            listElements[optionSetName].hide();
          });

        });
      });

      /**
       * Filters an option list.
       *
       * @param optionSetName
       *   The option set name.
       * @param filterText
       *   The text to filter by.
       */
      var filterList = function (optionSetName, filterText) {
        // Show all items if the textfield text is empty.
        if (filterText == '') {
          listElements[optionSetName].show();
          optionElements[optionSetName].forEach(function (optionText) {
            optionText.show();
          });

          return;
        }

        listElements[optionSetName].show();

        // Hide or show each list item.
        optionSetTexts[optionSetName].forEach(function (optionText, index) {
          var textMatch = optionText.search(new RegExp(filterText, 'i')) !== -1;

          optionElements[optionSetName][index].toggle(textMatch);
        });
      }

      /**
       * Attaches the option set to an autocomplete textfield that gets focus.
       */
      $textField.on('focus', function () {
        var optionSetName = this.getAttribute('data-option-set');

        if (listElements[optionSetName].attached != this) { // ARGH no effect!
          // Put the option set after the text field, and show it.
          listElements[optionSetName].show();
          $(this).after(listElements[optionSetName]);

          // Tell the option set which text field it is currently attached to.
          listElements[optionSetName].attached = this;
        }

        // Filter for the current text.
        filterList(optionSetName, this.value);
      });

      /**
       * Hides the option set when an autocomplete textfield loses focus.
       *
       * We exclude the dropdown list, so that clicks in the dropdown count as
       * still being in this focus.
       */
      $textField.on('focusout', function () {
        var siblingHover = $(this).parent().find("ul:hover");
        if (siblingHover.length) {
          return;
        }

        var optionSetName = $(this).attr('data-option-set');
        listElements[optionSetName].hide();
      });

      /**
       * Searches in the option set when the user types in the textfield.
       */
      $textField.on('keyup', function (e) {
        var optionSetName = this.getAttribute('data-option-set');
        var query = $(e.target).val().toLowerCase();

        filterList(optionSetName, query);
      });
    },

    detach: function (context, settings, trigger) {
      // In all cases, detach all the ULs from where they are, so that
      // they are not removed along with any DOM that gets replaced by AJAX.
      jQuery.each(listElements, function (key, $listElement) {
        $listElement.detach();
      });

    },
  };
})(jQuery, Drupal, drupalSettings);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc