PageSourceSearch

https://www.railbookers.com/core/modules/views/js/ajax_view.js?v=10.6.9

js railbookers.com collected 2026-10-02 05:31:50 UTC 7,091 bytes, 237 lines download raw bytes

1/**
2 * @file
3 * Handles AJAX fetching of views, including filter submission and response.
4 */
5
6(function ($, Drupal, drupalSettings) {
7  /**
8   * Attaches the AJAX behavior to exposed filters forms and key View links.
9   *
10   * @type {Drupal~behavior}
11   *
12   * @prop {Drupal~behaviorAttach} attach
13   *   Attaches ajaxView functionality to relevant elements.
14   */
15  Drupal.behaviors.ViewsAjaxView = {};
16  Drupal.behaviors.ViewsAjaxView.attach = function (context, settings) {
17    if (settings && settings.views && settings.views.ajaxViews) {
18      const {
19        views: { ajaxViews },
20      } = settings;
21      Object.keys(ajaxViews || {}).forEach((i) => {
22        Drupal.views.instances[i] = new Drupal.views.ajaxView(ajaxViews[i]);
23      });
24    }
25  };
26  Drupal.behaviors.ViewsAjaxView.detach = (context, settings, trigger) => {
27    if (trigger === 'unload') {
28      if (settings && settings.views && settings.views.ajaxViews) {
29        const {
30          views: { ajaxViews },
31        } = settings;
32        Object.keys(ajaxViews || {}).forEach((i) => {
33          const selector = `.js-view-dom-id-${ajaxViews[i].view_dom_id}`;
34          if ($(selector, context).length) {
35            delete Drupal.views.instances[i];
36            delete settings.views.ajaxViews[i];
37          }
38        });
39      }
40    }
41  };
42
43  /**
44   * @namespace
45   */
46  Drupal.views = {};
47
48  /**
49   * @type {object.<string, Drupal.views.ajaxView>}
50   */
51  Drupal.views.instances = {};
52
53  /**
54   * JavaScript object for a certain view.
55   *
56   * @constructor
57   *
58   * @param {object} settings
59   *   Settings object for the ajax view.
60   * @param {string} settings.view_dom_id
61   *   The DOM id of the view.
62   */
63  Drupal.views.ajaxView = function (settings) {
64    const selector = `.js-view-dom-id-${settings.view_dom_id}`;
65    this.$view = $(selector);
66
67    // Retrieve the path to use for views' ajax.
68    let ajaxPath = drupalSettings.views.ajax_path;
69
70    // If there are multiple views this might've ended up showing up multiple
71    // times.
72    if (ajaxPath.constructor.toString().includes('Array')) {
73      ajaxPath = ajaxPath[0];
74    }
75
76    // Check if there are any GET parameters to send to views.
77    let queryString = window.location.search || '';
78    if (queryString !== '') {
79      // Remove the question mark and Drupal path component if any.
80      queryString = queryString
81        .slice(1)
82        .replace(/q=[^&]+&?|page=[^&]+&?|&?render=[^&]+/, '');
83      if (queryString !== '') {
84        // If there is a '?' in ajaxPath, clean URL are on and & should be
85        // used to add parameters.
86        queryString = (/\?/.test(ajaxPath) ? '&' : '?') + queryString;
87      }
88    }
89
90    this.element_settings = {
91      url: ajaxPath + queryString,
92      submit: settings,
93      httpMethod: 'GET',
94      setClick: true,
95      event: 'click',
96      selector,
97      progress: { type: 'fullscreen' },
98    };
99
100    this.settings = settings;
101
102    // Add the ajax to exposed forms.
103    this.$exposed_form = $(
104      `.view-media-library form#views-exposed-form-${settings.view_name.replace(
105        /_/g,
106        '-',
107      )}-${settings.view_display_id.replace(
108        /_/g,
109        '-',
110      )}, form.views-exposed-form[data-drupal-target-view="${
111        settings.view_dom_id
112      }"], form.views-exposed-form[data-drupal-target-view="${
113        settings.view_name
114      }-${settings.view_display_id}"]`,
115    );
116    once('exposed-form', this.$exposed_form).forEach(
117      this.attachExposedFormAjax.bind(this),
118    );
119
120    // Add the ajax to pagers.
121    once(
122      'ajax-pager',
123      this.$view
124        // Don't attach to nested views. Doing so would attach multiple behaviors
125        // to a given element.
126        .filter(this.filterNestedViews.bind(this)),
127    ).forEach(this.attachPagerAjax.bind(this));
128
129    // Add a trigger to update this view specifically. In order to trigger a
130    // refresh use the following code.
131    //
132    // @code
133    // $('.view-name').trigger('RefreshView');
134    // @endcode
135    const selfSettings = $.extend({}, this.element_settings, {
136      event: 'RefreshView',
137      base: this.selector,
138      httpMethod: 'GET',
139      element: this.$view.get(0),
140    });
141    this.refreshViewAjax = Drupal.ajax(selfSettings);
142  };
143
144  /**
145   * @method
146   */
147  Drupal.views.ajaxView.prototype.attachExposedFormAjax = function () {
148    const that = this;
149    this.exposedFormAjax = [];
150    // Exclude the reset buttons so no AJAX behaviors are bound. Many things
151    // break during the form reset phase if using AJAX.
152    once(
153      'attach-ajax',
154      $(
155        'input[type=submit], button[type=submit], input[type=image]',
156        this.$exposed_form,
157      ).not('[data-drupal-selector=edit-reset]'),
158    ).forEach(function (button, index) {
159      const selfSettings = $.extend({}, that.element_settings, {
160        base: $(button).attr('id'),
161        element: button,
162      });
163      that.exposedFormAjax[index] = Drupal.ajax(selfSettings);
164    });
165  };
166
167  /**
168   * @return {boolean}
169   *   If there is at least one parent with a view class return false.
170   */
171  Drupal.views.ajaxView.prototype.filterNestedViews = function () {
172    // If there is at least one parent with a view class, this view
173    // is nested (e.g., an attachment). Bail.
174    return !this.$view.parents('.view').length;
175  };
176
177  /**
178   * Attach the ajax behavior to each link.
179   */
180  Drupal.views.ajaxView.prototype.attachPagerAjax = function () {
181    this.$view
182      .find(
183        '.js-pager__items a, th.views-field a, .attachment .views-summary a',
184      )
185      .each(this.attachPagerLinkAjax.bind(this));
186  };
187
188  /**
189   * Attach the ajax behavior to a singe link.
190   *
191   * @param {string} [id]
192   *   The ID of the link.
193   * @param {HTMLElement} link
194   *   The link element.
195   */
196  Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function (id, link) {
197    const $link = $(link);
198    const viewData = {};
199    const href = $link.attr('href');
200    // Construct an object using the settings defaults and then overriding
201    // with data specific to the link.
202    $.extend(
203      viewData,
204      this.settings,
205      Drupal.Views.parseQueryString(href),
206      // Extract argument data from the URL.
207      Drupal.Views.parseViewArgs(href, this.settings.view_base_path),
208    );
209
210    const selfSettings = $.extend({}, this.element_settings, {
211      submit: viewData,
212      base: false,
213      element: link,
214      httpMethod: 'GET',
215    });
216    this.pagerAjax = Drupal.ajax(selfSettings);
217  };
218
219  /**
220   * Views scroll to top ajax command.
221   *
222   * @param {Drupal.Ajax} [ajax]
223   *   A {@link Drupal.ajax} object.
224   * @param {object} response
225   *   Ajax response.
226   * @param {string} response.selector
227   *   Selector to use.
228   *
229   * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0.
230   *   Use Drupal.AjaxCommands.prototype.scrollTop().
231   *
232   * @see https://www.drupal.org/node/3344141
233   */
234  Drupal.AjaxCommands.prototype.viewsScrollTop = function (ajax, response) {
235    Drupal.AjaxCommands.prototype.scrollTop(ajax, response);
236  };
237})(jQuery, Drupal, drupalSettings);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.