lunr-8.x-1.0/js/search.js

js/search.js
/**
 * @file
 * Provides behaviors for Lunr search pages.
 */

(function ($, Drupal, drupalSettings) {

  /**
   * Stores globals needed for search.
   *
   * @type {object}
   */
  Drupal.lunr = Drupal.lunr || {
    worker: null,
    pages: {},
  };

  /**
   * Constructs an object representing a search page.
   *
   * @constructor
   *
   * @param {object} settings
   *   Settings for this search page.
   * @param {string} settings.indexPath
   *   The path to the index file.
   * @param {number} settings.id
   *   The ID for the lunr search entity.
   * @param {string} settings.documentPathPattern
   *   The path pattern for document files.
   * @param {string} settings.displayField
   *   The field to display for documents.
   * @param {number} settings.resultsPerPage
   *   The number of search results to display per page.
   * @param {object} $form
   *   The jQuery object for the form.
   */
  Drupal.lunrSearchPage = function (settings, $form) {
    this.settings = settings;
    this.documents = {};
    this.results = [];
    this.$progressElement = false;
    this.$form = $form;
  };

  /**
   * Shows progress while AJAX requests are made.
   */
  Drupal.lunrSearchPage.prototype.showProgress = function () {
    this.hideProgress();
    this.$form.addClass('lunr-loading');
    this.$form.removeClass('lunr-ready');
    this.$progressElement = $(Drupal.theme.lunrSearchProgress());
    $('body').after(this.$progressElement);
  };

  /**
   * Hides the progress element.
   */
  Drupal.lunrSearchPage.prototype.hideProgress = function () {
    this.$form.removeClass('lunr-loading');
    this.$form.addClass('lunr-ready');
    if (this.$progressElement) {
      this.$progressElement.remove();
    }
  };

  /**
   * Initializes the search page.
   */
  Drupal.lunrSearchPage.prototype.init = function () {
    this.$form.find('[data-lunr-auto-submit]').on('change', function () {
      this.$form.submit();
    }.bind(this));
    this.$form.on('submit', function (e) {
      e.preventDefault();
      var value = this.$form.find('.js-lunr-search-input').val();
      var parameters = {
        search: value,
        page: 1
      };
      this.$form.find('[data-lunr-search-field]').each(function () {
        var key = $(this).attr('data-lunr-search-field');
        if ($(this).attr('type') === 'checkbox' && !this.checked) {
          if (typeof parameters[key] === 'undefined') {
            parameters[key] = '';
          }
          return;
        }
        if (parameters[key]) {
          parameters[key] += ' ' + $(this).val();
        } else {
          parameters[key] = $(this).val();
        }
      });
      this.setParameters(parameters);
      this.searchByQuery();
    }.bind(this));
    this.hideProgress();
    this.searchByQuery();
  };

  /**
   * Executes a search based on the current query params.
   */
  Drupal.lunrSearchPage.prototype.searchByQuery = function () {
    var parameters = this.getParameters();
    var fields = {};
    this.$form.find('[data-lunr-search-field]').each(function () {
      var key = $(this).attr('data-lunr-search-field');
      if (key in parameters) {
        fields[key] = parameters[key];
        if ($(this).attr('type') === 'checkbox') {
          var values = parameters[key].split(' ');
          $(this).prop('checked', values.includes($(this).val()));
        }
        else {
          $(this).val(parameters[key]);
        }
      }
      else {
        if ($(this).attr('type') === 'checkbox') {
          $(this).prop('checked', false);
        }
        else {
          $(this).val('');
        }
      }
    });
    if (Object.keys(parameters).length) {
      var search = parameters['search'] ? parameters['search'] : '';
      this.$form.find('.js-lunr-search-input').val(search);
      this.showProgress();
      Drupal.lunr.worker.postMessage({
        type: 'search',
        search: search,
        fields: fields,
        operators: drupalSettings.lunrOperators ? drupalSettings.lunrOperators : {},
        id: this.settings.id,
      });
    }
  };

  /**
   * Displays a given page of search results.
   *
   * @param {number} page
   *   The page.
   * @param {boolean} shouldScroll
   *   Determines if page will scroll back to the form.
   */
  Drupal.lunrSearchPage.prototype.showPage = function (page, shouldScroll) {
    this.showProgress();
    var requests = {};
    var currentResults = this.results.slice(page * this.settings.resultsPerPage, (page * this.settings.resultsPerPage) + this.settings.resultsPerPage);
    currentResults.forEach(function (result) {
      var documentPage = result.ref.split(':')[0];
      if (!(documentPage in this.documents) && !(documentPage in requests)) {
        requests[documentPage] = $.ajax({
          url: this.settings.documentPathPattern.replace('PAGE', documentPage),
          type : 'GET',
          success: function (data) {
            this.documents[documentPage] = data;
          }.bind(this),
          error: function (request, error) {
            console.log('Error'); //@todo
          }
        });
      }
    }.bind(this));
    $.when.apply($, Object.values(requests)).then(function () {
      var $results = this.$form.siblings('.js-lunr-search-results');
      $results.empty();
      $results.append(Drupal.theme.lunrSearchResultCount({
        count: this.results.length,
        page: page
      }));
      currentResults.forEach(function (result) {
        $results.append(this.getRowElement(result.ref));
      }.bind(this));
      var $pager = $(Drupal.theme.lunrSearchPager({
        count: this.results.length,
        resultsPerPage: this.settings.resultsPerPage,
        page: page
      }));
      $pager.find('[data-page]').on('click', function (e) {
        e.preventDefault();
        var newPage = parseInt($(e.currentTarget).attr('data-page'));
        this.setParameter('page', newPage + 1);
        this.showPage(newPage, true);
      }.bind(this));
      $results.append($pager);
      if (shouldScroll) {
        this.scrollToForm();
      }
      this.hideProgress();
    }.bind(this));
  };

  /**
   * Scrolls to the top of the form.
   */
  Drupal.lunrSearchPage.prototype.scrollToForm = function () {
    $('html,body').animate({
      scrollTop: this.$form.offset().top - ($('#toolbar-bar').find('.toolbar-tab').outerHeight() || 0)
    }, 200);
  };

  /**
   * Gets the row element for a given reference ID.
   *
   * @param {string} ref
   *   The document reference ID in the format page:index
   *
   * @returns {object}
   *   A jQuery object representing the row.
   */
  Drupal.lunrSearchPage.prototype.getRowElement = function (ref) {
    var parts = ref.split(':');
    var document = this.documents[parts[0]][parts[1]];
    return $(Drupal.theme.lunrSearchResultWrapper()).append(document[this.settings.displayField]);
  };

  /**
   * Utility function for getting multiple query param values.
   *
   * @returns {object}
   *   An object mapping field keys to values.
   */
  Drupal.lunrSearchPage.prototype.getParameters = function () {
    if ('URLSearchParams' in window) {
      var values = {};
      var searchParams = new URLSearchParams(window.location.search);
      searchParams.forEach(function (value, key) {
        values[key] = value;
      });
      return values;
    }
    return {};
  };

  /**
   * Utility function for getting query param values.
   *
   * @param {string} name
   *   The query param name.
   *
   * @returns {*}
   *   The value for the query param.
   */
  Drupal.lunrSearchPage.prototype.getParameter = function (name) {
    if ('URLSearchParams' in window) {
      var searchParams = new URLSearchParams(window.location.search);
      return searchParams.get(name);
    }
    return false;
  };

  /**
   * Utility function for setting query param values.
   *
   * Credit to Anthony Manning-Franklin https://stackoverflow.com/a/41542008
   *
   * @param {string} name
   *   The query param name.
   * @param {*} value
   *   The query param value.
   */
  Drupal.lunrSearchPage.prototype.setParameter = function (name, value) {
    if ('URLSearchParams' in window) {
      var searchParams = new URLSearchParams(window.location.search);
      searchParams.set(name, value);
      var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
      history.pushState(null, '', newRelativePathQuery);
    }
    return;
  };

  /**
   * Utility function for setting multiple query param values.
   *
   * Credit to Anthony Manning-Franklin https://stackoverflow.com/a/41542008
   *
   * @param {object} parameters
   *   An object mapping parameter keys to values.
   */
  Drupal.lunrSearchPage.prototype.setParameters = function (parameters) {
    if ('URLSearchParams' in window) {
      var searchParams = new URLSearchParams(window.location.search);
      for (var key in parameters) {
        searchParams.set(key, parameters[key]);
      }
      var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
      history.pushState(null, '', newRelativePathQuery);
    }
    return;
  };

  /**
   * Displays search results.
   *
   * @param {array} results
   *   The search results.
   */
  Drupal.lunrSearchPage.prototype.showResults = function (results) {
    this.hideProgress();
    this.results = results;
    var initPage = parseInt(this.getParameter('page'));
    if (initPage && initPage > 0) {
      this.showPage(initPage - 1, false);
    }
    else {
      this.showPage(0, false);
    }
  };

  /**
   * Listens to messages from our worker.
   *
   * @param {MessageEvent} event
   *   The event.
   */
  function onWorkerMessage(event) {
    switch (event.data.type) {
      case 'loadIndexComplete':
        Drupal.lunr.pages[event.data.id].init();
        break;

      case 'searchComplete':
        Drupal.lunr.pages[event.data.id].showResults(event.data.results);
        break;

      default:
        throw new Error('Unknown message sent from lunr search worker.');
    }
  }

  /**
   * A Drupal behavior that initializes Lunr search pages.
   *
   * @type {Drupal~behavior}
   */
  Drupal.behaviors.lunrIndexForm = {
    attach: function (context) {
      $(once('lunr-search', 'form.js-lunr-search-page-form', context)).each(function () {
        var settings = drupalSettings.lunr.searchSettings[$(this).attr('data-lunr-search')];
        if (!Drupal.lunr.worker) {
          Drupal.lunr.worker = new Worker(drupalSettings.lunr.workerPath);
          Drupal.lunr.worker.onmessage = onWorkerMessage;
        }
        Drupal.lunr.worker.postMessage({
          type: 'loadIndex',
          id: settings.id,
          indexPath: settings.indexPath,
          lunrPath: drupalSettings.lunr.lunrPath
        });
        Drupal.lunr.pages[settings.id] = new Drupal.lunrSearchPage(settings, $(this));
        Drupal.lunr.pages[settings.id].showProgress();
        window.onpopstate = function () {
          Drupal.lunr.pages[settings.id].searchByQuery();
        };
      });
    }
  };

})(jQuery, Drupal, drupalSettings);

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

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