stacks-8.x-1.x-dev/modules/stacks_content_feed/js/grid.ajax.js

modules/stacks_content_feed/js/grid.ajax.js
(function ($, Drupal, drupalSettings) {

  // Set default ajax settings.
  var gridAjaxSettings_base = {
    url: '/ajax/grid',
    // This is the wrapper div for all ajax functionality.
    ajax_wrapper: '.ajax_wrapper',
    // This is the div where results will be replaced.
    ajax_results: '.ajax_results',
    ajax_filters: '.ajax_filter, .ajax_filter_checkbox:checked',
    effect: 'fade',
    progress: {
      // Normally either progress or bar, but we created a custom one.
      type: 'gridajax',
      message: Drupal.t('Loading...')
    }
  };

  // Contains the settings for each grid widget.
  var widget_settings = {};

  Drupal.behaviors.gridAjax = {
    smoothscroll: function(hash, speed) {
      // Set default offset for main frontend (for like a fixed nav bar)
      var offset = 0;

      if (drupalSettings.user.uid > 0) {
        // This user is logged in. Account for the nav bar.
        offset += 85;
      }

      if (!speed) {
        speed = 1000;
      }

      if ($(window).width() < 640) offset = 0;
      $('html,body').animate({scrollTop: $(hash).offset().top - offset}, speed);
    },

    attach: function (context, settings) {

      /**
       * Go through all ajax containers to put together the post data object.
       * This is done on page load and prevents us from having to do this for
       * every ajax call. We only want this to run once on initial page load.
       */
      $(once('grid-ajax', gridAjaxSettings_base.ajax_results), context).each(function () {
        var $ajax_results = $(this);
        var wrapper_id = $ajax_results.attr('id');
        var widget_id = $ajax_results.attr('widgetid');

        // Set all attributes on the div with the AJAX post.
        widget_settings[wrapper_id] = {};
        $.each(this.attributes, function () {
          if (this.specified) {
            widget_settings[wrapper_id][this.name] = this.value;
          }
        });

        // Do we need to bind to scroll for this grid? Triggers on the scroll
        // event, then clicks on the hidden pagination link in the html.
        if (widget_id in settings.stacksgrid.scroll) {
          $(window).on('scroll', function () {
            if (isScrolledIntoView($ajax_results)) {
              $('.ajax_results_pagination a:first()', $ajax_results).trigger('click');
            }
          });
        }
      });

      // Bind pagination links. This needs to be triggered when AJAX happens as well.
      $(once('grid-ajax-pagination', '.ajax_results_pagination a'), context).each(function () {
        gridAjax(this, 'click');
      });

      // Smooth scroll to top of results for pagination links.
      $(once('grid-ajax-smoothscroll', '.ajax_results_pagination:not(.load_more):not(.load_more):not(.load_more_scroll) a')).on('click', function () {
        var wrapper_id = $(this).closest(gridAjaxSettings_base.ajax_results)[0].getAttribute('id');
        Drupal.behaviors.gridAjax.smoothscroll('#' + wrapper_id, 500);
      });

      // Bind filter drop downs. This only needs to happen on page load.
      var hasDefaultValues = 0;
      $(once('grid-ajax', gridAjaxSettings_base.ajax_wrapper + ' .ajax_filter'), context).each(function () {
        // Set URL attached values (if exist) before attaching events.
        hasDefaultValues += setDefaultValue($(this));
        gridAjax(this, 'change');
      });

      // Handle filters that are checkboxes/radio buttons.
      $(once('grid-ajax', gridAjaxSettings_base.ajax_wrapper + ' .ajax_filter_checkbox_wrapper'), context).each(function () {
        // Get the correct object for the checkboxes.
        var object = $('input[name="' + $(this).attr('fieldname') + '"]');
        for (i = 0; i < object.length; i++) {
          gridAjax(object[i], 'change');
        }
      });

      // Trigger ajax call for search field.
      $(once('grid-ajax-submit', '.filter_search_form')).submit(function (e) {
        e.preventDefault();
        $('.filter_search', this).change();
      });

      // Triggers ajax if the form is filled with default URL parameters.
      if (hasDefaultValues > 0) {
        $('select.ajax_filter').last().trigger('change');
      }

      // Add an active class when the radio filter is checked.
      $(once('radio-change', '.radio-active input')).change(function () {

        var $radio = $(this);
        var $wrapper = $radio.parent().parent();

        // Remove is-active class from all other radios.
        $('label', $wrapper).removeClass('is-active');

        // Add class to the selected option.
        if (this.checked) {
          $radio.parent().addClass('is-active');
        }
      });

      /**
       * Do AJAX on page load.
       *
       * If the attribute ajaxpageload=1 on the ajax_results div, we need to
       * load the results via ajax on page load. We do this by setting a "load"
       * event on ajax_results and triggering it.
       */
      //$(gridAjaxSettings_base.ajax_results + '[ajaxpageload="1"]', context).once('grid-ajax-page-load').each(function () {
      //ajaxPageLoad(this);
      //});
    }
  };

  /**
   * Function for parsing query strings
   */
  function parseQueryString(query) {
    var args = {};
    var pos = query.indexOf('?');
    if (pos !== -1) {
      query = query.substring(pos + 1);
    }
    var pair;
    var pairs = query.split('&');
    for (var i = 0; i < pairs.length; i++) {
      pair = pairs[i].split('=');
      // Ignore the 'q' path argument, if present.
      if (pair[0] !== 'q' && pair[1]) {
        args[decodeURIComponent(pair[0].replace(/\+/g, ' '))] = decodeURIComponent(pair[1].replace(/\+/g, ' '));
      }
    }
    return args;
  }

  /**
   * Main function for creating the Drupal.ajax events.
   */
  function gridAjax(object, event_target) {
    var gridAjaxSettings = jQuery.extend({}, gridAjaxSettings_base);

    var $object = $(object);
    var $ajax_wrapper = $object.closest(gridAjaxSettings.ajax_wrapper);
    var $ajax_results = $(gridAjaxSettings.ajax_results, $ajax_wrapper);

    var wrapper_id = $ajax_results.attr('id');
    var widget_id = $ajax_results.attr('widgetid');

    if ($object.parent().hasClass('pager__item') ||
      $object.parent().parent().hasClass('js-pager__items') ||
      $object.closest('div.ajax_results_pagination').hasClass('load_more') ||
      $object.closest('div.ajax_results_pagination').hasClass('load_more_scroll') ||
      $object.attr('rel') == 'prev' ||
      $object.attr('rel') == 'next'
    ) {
      // Fix the URL when multiple pagers
      var pagerHref = parseQueryString($object.attr('href'));
      // Explode query to get the right page number
      var pageAttrs = pagerHref.page.split(",");
      var validQueryComponents = pageAttrs.slice(0, parseInt(widget_id) + 1);
      widget_settings[wrapper_id].page = pageAttrs[widget_id];
      widget_settings[wrapper_id].pager_element = widget_id;
      var fixedPageLink = '?_wrapper_format=drupal_ajax&page=' + pageAttrs[widget_id];
      $object.attr('href', fixedPageLink);
    }

    // Add url query to url. Mainly to get the page parameter.
    if (object.hasAttribute('href')) {
      gridAjaxSettings.url += $object.attr('href');
    }

    gridAjaxSettings.wrapper = wrapper_id;
    gridAjaxSettings.event = event_target;
    gridAjaxSettings.element = object;

    // Send the widget data with the ajax post.
    gridAjaxSettings.submit = widget_settings[wrapper_id];

    var ajax = Drupal.ajax(gridAjaxSettings);

    // Add filters values before sending data. We overrite default Drupal.ajax
    // behavior.
    //TODO: fix this function call or find a different way to alter default AJAX handlers
    Drupal.Ajax.prototype.beforeSerialize = function (element, options) {

      var requestURL = options.url;

      if (requestURL.includes('ajax/grid')) {
        // Include default Drupal.Ajax.prototype.beforeSerialize code.
        options.data[Drupal.Ajax.AJAX_REQUEST_PARAMETER] = 1;
        var pageState = drupalSettings.ajaxPageState;
        options.data['ajax_page_state[theme]'] = pageState.theme;
        options.data['ajax_page_state[theme_token]'] = pageState.theme_token;
        options.data['ajax_page_state[libraries]'] = pageState.libraries;

        // Add the data for the filters.
        options.data['filters'] = getFilters(options);

      } else {
        // Allow detaching behaviors to update field values before collecting them.
        // This is only needed when field values are added to the POST data, so only
        // when there is a form such that this.$form.ajaxSubmit() is used instead of
        // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize()
        // isn't called, but don't rely on that: explicitly check this.$form.
        if (this.$form) {
          var settings = this.settings || drupalSettings;
          Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize');
        }

        // Inform Drupal that this is an AJAX request.
        options.data[Drupal.Ajax.AJAX_REQUEST_PARAMETER] = 1;

        // Allow Drupal to return new JavaScript and CSS files to load without
        // returning the ones already loaded.
        // @see \Drupal\Core\Theme\AjaxBasePageNegotiator
        // @see \Drupal\Core\Asset\LibraryDependencyResolverInterface::getMinimalRepresentativeSubset()
        // @see system_js_settings_alter()
        var pageState = drupalSettings.ajaxPageState;
        options.data['ajax_page_state[theme]'] = pageState.theme;
        options.data['ajax_page_state[theme_token]'] = pageState.theme_token;
        options.data['ajax_page_state[libraries]'] = pageState.libraries;
      }
    };

    return ajax;
  }

  /**
   * Put together the filters data object to send with the AJAX. We need to
   * trigger this after every ajax request to make sure we have the correct
   * filter options.
   */
  function getFilters(options) {
    var $get_filters = $('#' + options.data['id']).closest(gridAjaxSettings_base.ajax_wrapper).find(gridAjaxSettings_base.ajax_filters);

    var filters = {};
    $get_filters.each(function () {
      var $filter_object = $(this);
      if ($filter_object.val() != '' && !$filter_object.hasClass('ajax_filter_checkbox')) {
        var filter_name = $filter_object.attr('name');
        if ($filter_object.attr('field')) {
          var field_name = $filter_object.attr('field');

          // For certain filters like taxonomy, add one more level to the filter.
          if ($filter_object.attr('filtertype')) {

            var filter_type = $filter_object.attr('filtertype');
            if (typeof filters[filter_type] === 'undefined') {
              filters[filter_type] = {};
            }

            filters[filter_type][filter_name] = {};
            filters[filter_type][filter_name] = [$filter_object.val()];
          }
          else {
            filters[filter_name] = {};
            filters[filter_name][field_name] = [$filter_object.val()];
          }

        }
        else {
          filters[filter_name] = [$filter_object.val()];
        }
      }
      else if ($filter_object.hasClass('ajax_filter_checkbox')) {
        // Checkboxes/radios.
        var field_name = $filter_object.attr('name');
        filters[field_name] = [];

        // Since this could be a checkbox, there might be multiple selected values.
        $($filter_object).each(function () {
          filters[field_name].push($(this).val());
        });

      }
    });

    return filters;
  }

  /**
   * Function to set prefixed values that come from the URL (if exist).
   */
  function setDefaultValue(object) {
    var found = 0;
    if (object.is('select') && (parameter = getParameterByName(object.attr('name')))) {
      object.find('option').each(function () {
        if ($(this).val() == parameter) {
          object.val(parameter).change().trigger("chosen:updated");
          found = true;
        }
      });
    }

    if (found) {
      return 1;
    }
    else {
      return 0;
    }
  }

  /**
   * Function to get URL parameters.
   */
  function getParameterByName(name) {
    if (typeof name !== "undefined") {
      url = window.location.href;
      name = name.replace(/[\[\]]/g, "\\$&");
      var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
      if (!results) return null;
      if (!results[2]) return '';
      return decodeURIComponent(results[2].replace(/\+/g, " "));
    }
  }

  /**
   * Call AJAX for a grid on page load.
   *
   * Default Drupal.ajax works, but it doesn't seems to get rid of the progress
   * loaders, except for the last one. So we use setTimeout() to manually
   * delete the progress loaders.
   */
  var ajax_load_delay_counter = 200;

  function ajaxPageLoad(cur_this) {
    var $object = $(cur_this);
    var $ajax_wrapper = $object.closest(gridAjaxSettings_base.ajax_wrapper);
    gridAjax(cur_this, 'load');
    $object.trigger('load');

    setTimeout(function () {
      $('.ajax-progress', $ajax_wrapper).remove();
    }, ajax_load_delay_counter);

    ajax_load_delay_counter += 200;
  }

  /**
   * See if something something is viewable and if so, returns true.
   */
  var $window = $(window);

  function isScrolledIntoView($elem) {
    var docViewTop = $window.scrollTop();
    var docViewBottom = docViewTop + $window.height();
    var elemTop = $elem.offset().top;
    var elemBottom = elemTop + $elem.height();
    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
  }

  /**
   * Create a new progress bar "type" option (gridajax).
   *
   * We make sure to attach the loader to the location we are expecting.
   */
  Drupal.Ajax.prototype.setProgressIndicatorGridajax = function () {
    this.progress.element = $('<div>', {
      class: 'ajax-progress ajax-progress-gridajax',
      html: $('<div>', {
        class: 'gridajax',
        html: '\u00a0'
      })
    });
    if (this.progress.message) {
      this.progress.element.find('.gridajax').after('<div class="message">' + this.progress.message + '</div>');
    }
    $(this.wrapper).after(this.progress.element);
  };

  /**
   * Create a jquery method to equalize the row of columns.
   */
  $.fn.ajaxequalizer = function () {
    setTimeout(function () {
      $('.js-equal').each(function () {
        $(this).equalize({
          children: '.js-equal__item',
          reset: true,
          equalize: 'innerHeight'
        });
      });
    }, 1500);
  };

})(jQuery, Drupal, drupalSettings);

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

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