PageSourceSearch

https://rusbestrailways.ru/sites/all/modules/better_exposed_filters/better_exposed_filters.js?r7ndte

js rusbestrailways.ru collected 2026-10-02 20:45:38 UTC 17,032 bytes, 414 lines download raw bytes

1/**
2 * @file better_exposed_filters.js
3 *
4 * Provides some client-side functionality for the Better Exposed Filters module
5 */
6(function ($) {
7  Drupal.behaviors.betterExposedFilters = {
8    attach: function(context) {
9      // Add highlight class to checked checkboxes for better theming
10      $('.bef-tree input[type=checkbox], .bef-checkboxes input[type=checkbox]')
11        // Highlight newly selected checkboxes
12        .change(function() {
13          _bef_highlight(this, context);
14        })
15        .filter(':checked').closest('.form-item', context).addClass('highlight')
16      ;
17    }
18  };
19
20  Drupal.behaviors.betterExposedFiltersSelectAllNone = {
21    attach: function(context) {
22
23      /*
24       * Add Select all/none links to specified checkboxes
25       */
26      var selected = $('.form-checkboxes.bef-select-all-none:not(.bef-processed)');
27      if (selected.length) {
28        var selAll = Drupal.t('Select All');
29        var selNone = Drupal.t('Select None');
30
31        // Set up a prototype link and event handlers
32        var link = $('<a class="bef-toggle" href="#">'+ selAll +'</a>')
33        link.click(function(event) {
34          // Don't actually follow the link...
35          event.preventDefault();
36          event.stopPropagation();
37
38          if (selAll == $(this).text()) {
39            // Select all the checkboxes
40            $(this)
41              .html(selNone)
42              .siblings('.bef-checkboxes, .bef-tree')
43                .find('.form-item input:checkbox').each(function() {
44                  $(this).attr('checked', true);
45                  _bef_highlight(this, context);
46                })
47              .end()
48
49              // attr() doesn't trigger a change event, so we do it ourselves. But just on
50              // one checkbox otherwise we have many spinning cursors
51              .find('input[type=checkbox]:first').change()
52            ;
53          }
54          else {
55            // Unselect all the checkboxes
56            $(this)
57              .html(selAll)
58              .siblings('.bef-checkboxes, .bef-tree')
59                .find('.form-item input:checkbox').each(function() {
60                  $(this).attr('checked', false);
61                  _bef_highlight(this, context);
62                })
63              .end()
64
65              // attr() doesn't trigger a change event, so we do it ourselves. But just on
66              // one checkbox otherwise we have many spinning cursors
67              .find('input[type=checkbox]:first').change()
68            ;
69          }
70        });
71
72        // Add link to the page for each set of checkboxes.
73        selected
74          .addClass('bef-processed')
75          .each(function(index) {
76            // Clone the link prototype and insert into the DOM
77            var newLink = link.clone(true);
78
79            newLink.insertBefore($('.bef-checkboxes, .bef-tree', this));
80
81            // If all checkboxes are already checked by default then switch to Select None
82            if ($('input:checkbox:checked', this).length == $('input:checkbox', this).length) {
83              newLink.click();
84            }
85          })
86        ;
87      }
88
89      // Check for and initialize datepickers
90      var befSettings = Drupal.settings.better_exposed_filters;
91      if (befSettings && befSettings.datepicker && befSettings.datepicker_options && $.fn.datepicker) {
92        var opt = befSettings.datepicker_options.dateformat ? {dateFormat: befSettings.datepicker_options.dateformat} : {};
93        $('.bef-datepicker').datepicker(opt);
94      }
95
96    }                   // attach: function() {
97  };                    // Drupal.behaviors.better_exposed_filters = {
98
99  Drupal.behaviors.betterExposedFiltersAllNoneNested = {
100    attach:function (context, settings) {
101      $('.form-checkboxes.bef-select-all-none-nested li').has('ul').once('bef-all-none-nested', function () {
102        $(this)
103          // To respect term depth, check/uncheck child term checkboxes.
104          .find('input.form-checkboxes:first')
105          .click(function() {
106            $(this).parents('li:first').find('ul input.form-checkboxes').attr('checked', $(this).attr('checked'));
107          })
108          .end()
109          // When a child term is checked or unchecked, set the parent term's
110          // status.
111          .find('ul input.form-checkboxes')
112          .click(function() {
113            var checked = $(this).attr('checked');
114            // Determine the number of unchecked sibling checkboxes.
115            var ct = $(this).parents('ul:first').find('input.form-checkboxes:not(:checked)').size();
116            // If the child term is unchecked, uncheck the parent.
117            // If all sibling terms are checked, check the parent.
118            if (!checked || !ct) {
119              $(this).parents('li:first').parents('li:first').find('input.form-checkboxes:first').attr('checked', checked);
120            }
121          });
122      });
123    }
124  }
125
126  Drupal.behaviors.better_exposed_filters_slider = {
127    attach: function(context, settings) {
128      var befSettings = settings.better_exposed_filters;
129      if (befSettings && befSettings.slider && befSettings.slider_options) {
130        $.each(befSettings.slider_options, function(i, sliderOptions) {
131          // Only make one slider per filter.
132          $("#" + sliderOptions.viewId + " #edit-" + sliderOptions.id + "-wrapper").once('slider-filter', function() {
133            var $input = $(this).find('input[type=text]');
134
135            // This is a "between" or "not between" filter with two values.
136            if ($input.length == 2) {
137              var $min = $input.parent().find('input#edit-' + sliderOptions.id + '-min'),
138                  $max = $input.parent().find('input#edit-' + sliderOptions.id + '-max'),
139                  default_min,
140                  default_max;
141
142              if (!$min.length || !$max.length) {
143                return;
144              }
145
146              // Get the default values.
147              // We use slider min & max if there are no defaults.
148              default_min = parseFloat(($min.val() == '') ? sliderOptions.min : $min.val(), 10);
149              default_max = parseFloat(($max.val() == '') ? sliderOptions.max : $max.val(), 10);
150              // Set the element value in case we are using the slider min & max.
151              $min.val(default_min);
152              $max.val(default_max);
153
154              $min.parents('div.views-widget').after(
155                $('<div class="bef-slider"></div>').slider({
156                  range: true,
157                  min: parseFloat(sliderOptions.min, 10),
158                  max: parseFloat(sliderOptions.max, 10),
159                  step: parseFloat(sliderOptions.step, 10),
160                  animate: sliderOptions.animate ? sliderOptions.animate : false,
161                  orientation: sliderOptions.orientation,
162                  values: [default_min, default_max],
163                  // Update the textfields as the sliders are moved
164                  slide: function (event, ui) {
165                    $min.val(ui.values[0]);
166                    $max.val(ui.values[1]);
167                  },
168                  // This fires when the value is set programmatically or the
169                  // stop event fires.
170                  // This takes care of the case that a user enters a value
171                  // into the text field that is not a valid step of the slider.
172                  // In that case the slider will go to the nearest step and
173                  // this change event will update the text area.
174                  change: function (event, ui) {
175                    $min.val(ui.values[0]);
176                    $max.val(ui.values[1]);
177                  },
178                  // Attach stop listeners.
179                  stop: function(event, ui) {
180                    // Click the auto submit button.
181                    $(this).parents('form').find('.ctools-auto-submit-click').click();
182                  }
183                })
184              );
185
186              // Update the slider when the fields are updated.
187              $min.blur(function() {
188                befUpdateSlider($(this), 0, sliderOptions);
189              });
190              $max.blur(function() {
191                befUpdateSlider($(this), 1, sliderOptions);
192              });
193            }
194            // This is single value filter.
195            else if ($input.length == 1) {
196              if ($input.attr('id') != 'edit-' + sliderOptions.id) {
197                return;
198              }
199
200              // Get the default value. We use slider min if there is no default.
201              var default_value = parseFloat(($input.val() == '') ? sliderOptions.min : $input.val(), 10);
202              // Set the element value in case we are using the slider min.
203              $input.val(default_value);
204
205              $input.parents('div.views-widget').after(
206                $('<div class="bef-slider"></div>').slider({
207                  min: parseFloat(sliderOptions.min, 10),
208                  max: parseFloat(sliderOptions.max, 10),
209                  step: parseFloat(sliderOptions.step, 10),
210                  animate: sliderOptions.animate ? sliderOptions.animate : false,
211                  orientation: sliderOptions.orientation,
212                  value: default_value,
213                  // Update the textfields as the sliders are moved.
214                  slide: function (event, ui) {
215                    $input.val(ui.value);
216                  },
217                  // This fires when the value is set programmatically or the
218                  // stop event fires.
219                  // This takes care of the case that a user enters a value
220                  // into the text field that is not a valid step of the slider.
221                  // In that case the slider will go to the nearest step and
222                  // this change event will update the text area.
223                  change: function (event, ui) {
224                    $input.val(ui.value);
225                  },
226                  // Attach stop listeners.
227                  stop: function(event, ui) {
228                    // Click the auto submit button.
229                    $(this).parents('form').find('.ctools-auto-submit-click').click();
230                  }
231                })
232              );
233
234              // Update the slider when the field is updated.
235              $input.blur(function() {
236                befUpdateSlider($(this), null, sliderOptions);
237              });
238            }
239            else {
240              return;
241            }
242          })
243        });
244      }
245    }
246  };
247
248  // This is only needed to provide ajax functionality
249  Drupal.behaviors.better_exposed_filters_select_as_links = {
250    attach: function(context, settings) {
251
252      $('.bef-select-as-links', context).once(function() {
253        var $element = $(this);
254
255        // Check if ajax submission is enabled. If it's not enabled then we
256        // don't need to attach our custom submission handling, because the
257        // links are already properly built.
258
259        // First check if any ajax views are contained in the current page.
260        if (typeof settings.views == 'undefined' || typeof settings.views.ajaxViews == 'undefined') {
261          return;
262        }
263
264        // Now check that the view for which the current filter block is used,
265        // is part of the configured ajax views.
266        var $uses_ajax = false;
267        $.each(settings.views.ajaxViews, function(i, item) {
268          var $view_name = item.view_name.replace(/_/g, '-');
269          var $view_display_id = item.view_display_id.replace(/_/g, '-');
270          var $id = 'views-exposed-form-' + $view_name + '-' + $view_display_id;
271          var $form_id = $element.parents('form').attr('id');
272          if ($form_id == $id) {
273            $uses_ajax = true;
274            return;
275          }
276        });
277
278        // If no ajax is used for form submission, we quit here.
279        if (!$uses_ajax) {
280          return;
281        }
282
283        // Attach selection toggle and form submit on click to each link.
284        $(this).find('a').click(function(event) {
285          var $wrapper = $(this).parents('.bef-select-as-links');
286          var $options = $wrapper.find('select option');
287          // We have to prevent the page load triggered by the links.
288          event.preventDefault();
289          event.stopPropagation();
290          // Un select old select value.
291          $wrapper.find('select option').removeAttr('selected');
292
293          // Set the corresponding option inside the select element as selected.
294          var link_text = $(this).text();
295          $selected = $options.filter(function() {
296            return $(this).text() == link_text;
297          });
298          $selected.attr('selected', 'selected');
299          $wrapper.find('.bef-new-value').val($selected.val());
300          $wrapper.find('a').removeClass('active');
301          $(this).addClass('active');
302          // Submit the form.
303          $wrapper.parents('form').find('.views-submit-button *[type=submit]').click();
304        });
305      });
306    }
307  };
308
309  Drupal.behaviors.betterExposedFiltersRequiredFilter = {
310    attach: function(context, settings) {
311      // Required checkboxes should re-check all inputs if a user un-checks
312      // them all.
313      $('.bef-select-as-checkboxes', context).once('bef-required-filter').ajaxComplete(function (e, xhr, s) {
314        var $element = $(this);
315
316        if (typeof settings.views == 'undefined' || typeof settings.views.ajaxViews == 'undefined') {
317          return;
318        }
319
320        // Now check that the view for which the current filter block is used,
321        // is part of the configured ajax views.
322        var $view_name;
323        var $view_display_id;
324        var $uses_ajax = false;
325        $.each(settings.views.ajaxViews, function(i, item) {
326          $view_name = item.view_name;
327          $view_display_id = item.view_display_id;
328          var $id = 'views-exposed-form-' + $view_name.replace(/_/g, '-') + '-' + $view_display_id.replace(/_/g, '-');
329          var $form_id = $element.parents('form').attr('id');
330          if ($form_id == $id) {
331            $uses_ajax = true;
332            return;
333          }
334        });
335
336        var $filter_name = $('input', this).attr('name').slice(0, -2);
337        if (Drupal.settings.better_exposed_filters.views[$view_name].displays[$view_display_id].filters[$filter_name].required && $('input:checked', this).length == 0) {
338          $('input', this).prop('checked', true);
339        }
340      });
341    }
342  }
343
344  /*
345   * Helper functions
346   */
347
348  /**
349   * Adds/Removes the highlight class from the form-item div as appropriate
350   */
351  function _bef_highlight(elem, context) {
352    $elem = $(elem, context);
353    $elem.attr('checked')
354      ? $elem.closest('.form-item', context).addClass('highlight')
355      : $elem.closest('.form-item', context).removeClass('highlight');
356  }
357
358  /**
359   * Update a slider when a related input element is changed.
360   *
361   * We don't need to check whether the new value is valid based on slider min,
362   * max, and step because the slider will do that automatically and then we
363   * update the textfield on the slider's change event.
364   *
365   * We still have to make sure that the min & max values of a range slider
366   * don't pass each other though, however once this jQuery UI bug is fixed we
367   * won't have to. - http://bugs.jqueryui.com/ticket/3762
368   *
369   * @param $el
370   *   A jQuery object of the updated element.
371   * @param valIndex
372   *   The index of the value for a range slider or null for a non-range slider.
373   * @param sliderOptions
374   *   The options for the current slider.
375   */
376  function befUpdateSlider($el, valIndex, sliderOptions) {
377    var val = parseFloat($el.val(), 10),
378        currentMin = $el.parents('div.views-widget').next('.bef-slider').slider('values', 0),
379        currentMax = $el.parents('div.views-widget').next('.bef-slider').slider('values', 1);
380    // If we have a range slider.
381    if (valIndex != null) {
382      // Make sure the min is not more than the current max value.
383      if (valIndex == 0 && val > currentMax) {
384        val = currentMax;
385      }
386      // Make sure the max is not more than the current max value.
387      if (valIndex == 1 && val < currentMin) {
388        val = currentMin;
389      }
390      // If the number is invalid, go back to the last value.
391      if (isNaN(val)) {
392        val = $el.parents('div.views-widget').next('.bef-slider').slider('values', valIndex);
393      }
394    }
395    else {
396      // If the number is invalid, go back to the last value.
397      if (isNaN(val)) {
398        val = $el.parents('div.views-widget').next('.bef-slider').slider('value');
399      }
400    }
401    // Make sure we are a number again.
402    val = parseFloat(val, 10);
403    // Set the slider to the new value.
404    // The slider's change event will then update the textfield again so that
405    // they both have the same value.
406    if (valIndex != null) {
407      $el.parents('div.views-widget').next('.bef-slider').slider('values', valIndex, val);
408    }
409    else {
410      $el.parents('div.views-widget').next('.bef-slider').slider('value', val);
411    }
412  }
413
414}) (jQuery);

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.