PageSourceSearch

https://www.redaction.io/sites/default/files/js/js_MRdvkC2u4oGsp5wVxBG1pGV5NrCPW3mssHxIn6G9tGE.js

js redaction.io collected 2026-09-25 22:59:31 UTC 9,917 bytes, 282 lines download raw bytes

1/**
2 * @file
3 * bootstrap.js
4 *
5 * Provides general enhancements and fixes to Bootstrap's JS files.
6 */
7
8var Drupal = Drupal || {};
9
10(function($, Drupal){
11  "use strict";
12
13  var $document = $(document);
14
15  Drupal.behaviors.bootstrap = {
16    attach: function(context) {
17      // Provide some Bootstrap tab/Drupal integration.
18      $(context).find('.tabbable').once('bootstrap-tabs', function () {
19        var $wrapper = $(this);
20        var $tabs = $wrapper.find('.nav-tabs');
21        var $content = $wrapper.find('.tab-content');
22        var borderRadius = parseInt($content.css('borderBottomRightRadius'), 10);
23        var bootstrapTabResize = function() {
24          if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
25            $content.css('min-height', $tabs.outerHeight());
26          }
27        };
28        // Add min-height on content for left and right tabs.
29        bootstrapTabResize();
30        // Detect tab switch.
31        if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
32          $tabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
33            bootstrapTabResize();
34            if ($wrapper.hasClass('tabs-left')) {
35              if ($(e.target).parent().is(':first-child')) {
36                $content.css('borderTopLeftRadius', '0');
37              }
38              else {
39                $content.css('borderTopLeftRadius', borderRadius + 'px');
40              }
41            }
42            else {
43              if ($(e.target).parent().is(':first-child')) {
44                $content.css('borderTopRightRadius', '0');
45              }
46              else {
47                $content.css('borderTopRightRadius', borderRadius + 'px');
48              }
49            }
50          });
51        }
52      });
53    }
54  };
55
56  /**
57   * Behavior for .
58   */
59  Drupal.behaviors.bootstrapFormHasError = {
60    attach: function (context, settings) {
61      if (settings.bootstrap && settings.bootstrap.formHasError) {
62        var $context = $(context);
63        $context.find('.form-item.has-error:not(.form-type-password.has-feedback)').once('error', function () {
64          var $formItem = $(this);
65          var $input = $formItem.find(':input');
66          $input.on('keyup focus blur', function () {
67            var value = $input.val() || false;
68            $formItem[value ? 'removeClass' : 'addClass']('has-error');
69            $input[value ? 'removeClass' : 'addClass']('error');
70          });
71        });
72      }
73    }
74  };
75
76  /**
77   * Bootstrap Popovers.
78   */
79  Drupal.behaviors.bootstrapPopovers = {
80    attach: function (context, settings) {
81      // Immediately return if popovers are not available.
82      if (!settings.bootstrap || !settings.bootstrap.popoverEnabled || !$.fn.popover) {
83        return;
84      }
85
86      // Popover autoclose.
87      if (settings.bootstrap.popoverOptions.triggerAutoclose) {
88        var $currentPopover = null;
89        $document
90          .on('show.bs.popover', '[data-toggle=popover]', function () {
91            var $trigger = $(this);
92            var popover = $trigger.data('bs.popover');
93
94            // Only keep track of clicked triggers that we're manually handling.
95            if (popover.options.originalTrigger === 'click') {
96              if ($currentPopover && !$currentPopover.is($trigger)) {
97                $currentPopover.popover('hide');
98              }
99              $currentPopover = $trigger;
100            }
101          })
102          .on('click', function (e) {
103            var $target = $(e.target);
104            var popover = $target.is('[data-toggle=popover]') && $target.data('bs.popover');
105            if ($currentPopover && !$target.is('[data-toggle=popover]') && !$target.closest('.popover.in')[0]) {
106              $currentPopover.popover('hide');
107              $currentPopover = null;
108            }
109          })
110        ;
111      }
112
113      var elements = $(context).find('[data-toggle=popover]').toArray();
114      for (var i = 0; i < elements.length; i++) {
115        var $element = $(elements[i]);
116        var options = $.extend({}, $.fn.popover.Constructor.DEFAULTS, settings.bootstrap.popoverOptions, $element.data());
117
118        // Store the original trigger.
119        options.originalTrigger = options.trigger;
120
121        // If the trigger is "click", then we'll handle it manually here.
122        if (options.trigger === 'click') {
123          options.trigger = 'manual';
124        }
125
126        // Retrieve content from a target element.
127        var target = options.target || $element.is('a[href^="#"]') && $element.attr('href');
128        var $target = $document.find(target).clone();
129        if (!options.content && $target[0]) {
130          $target.removeClass('element-invisible hidden').removeAttr('aria-hidden');
131          options.content = $target.wrap('<div/>').parent()[options.html ? 'html' : 'text']() || '';
132        }
133
134        // Initialize the popover.
135        $element.popover(options);
136
137        // Handle clicks manually.
138        if (options.originalTrigger === 'click') {
139          // To ensure the element is bound multiple times, remove any
140          // previously set event handler before adding another one.
141          $element
142            .off('click.drupal.bootstrap.popover')
143            .on('click.drupal.bootstrap.popover', function (e) {
144              $(this).popover('toggle');
145              e.preventDefault();
146              e.stopPropagation();
147            })
148          ;
149        }
150      }
151    },
152    detach: function (context, settings) {
153      // Immediately return if popovers are not available.
154      if (!settings.bootstrap || !settings.bootstrap.popoverEnabled || !$.fn.popover) {
155        return;
156      }
157
158      // Destroy all popovers.
159      $(context).find('[data-toggle="popover"]')
160        .off('click.drupal.bootstrap.popover')
161        .popover('destroy')
162      ;
163    }
164  };
165
166  /**
167   * Bootstrap Tooltips.
168   */
169  Drupal.behaviors.bootstrapTooltips = {
170    attach: function (context, settings) {
171      if (settings.bootstrap && settings.bootstrap.tooltipEnabled) {
172        var elements = $(context).find('[data-toggle="tooltip"]').toArray();
173        for (var i = 0; i < elements.length; i++) {
174          var $element = $(elements[i]);
175          var options = $.extend({}, settings.bootstrap.tooltipOptions, $element.data());
176          $element.tooltip(options);
177        }
178      }
179    }
180  };
181
182  /**
183   * Anchor fixes.
184   */
185  var $scrollableElement = $();
186  Drupal.behaviors.bootstrapAnchors = {
187    attach: function(context, settings) {
188      var i, elements = ['html', 'body'];
189      if (!$scrollableElement.length) {
190        for (i = 0; i < elements.length; i++) {
191          var $element = $(elements[i]);
192          if ($element.scrollTop() > 0) {
193            $scrollableElement = $element;
194            break;
195          }
196          else {
197            $element.scrollTop(1);
198            if ($element.scrollTop() > 0) {
199              $element.scrollTop(0);
200              $scrollableElement = $element;
201              break;
202            }
203          }
204        }
205      }
206      if (!settings.bootstrap || settings.bootstrap.anchorsFix !== '1') {
207        return;
208      }
209      var anchors = $(context).find('a').toArray();
210      for (i = 0; i < anchors.length; i++) {
211        if (!anchors[i].scrollTo) {
212          this.bootstrapAnchor(anchors[i]);
213        }
214      }
215      $scrollableElement.once('bootstrap-anchors', function () {
216        $scrollableElement.on('click.bootstrap-anchors', 'a[href*="#"]:not([data-toggle],[data-target],[data-slide])', function(e) {
217          if (this.scrollTo) {
218            this.scrollTo(e);
219          }
220        });
221      });
222    },
223    bootstrapAnchor: function (element) {
224      element.validAnchor = element.nodeName === 'A' && (location.hostname === element.hostname || !element.hostname) && (element.hash.replace(/#/,'').length > 0);
225      element.scrollTo = function(event) {
226        var attr = 'id';
227        var $target = $(element.hash);
228        // Check for anchors that use the name attribute instead.
229        if (!$target.length) {
230          attr = 'name';
231          $target = $('[name="' + element.hash.replace('#', '') + '"]');
232        }
233        // Immediately stop if no anchors are found.
234        if (!this.validAnchor && !$target.length) {
235          return;
236        }
237        // Anchor is valid, continue if there is an offset.
238        var offset = $target.offset().top - parseInt($scrollableElement.css('paddingTop'), 10) - parseInt($scrollableElement.css('marginTop'), 10);
239        if (offset > 0) {
240          if (event) {
241            event.preventDefault();
242          }
243          var $fakeAnchor = $('<div/>')
244            .addClass('element-invisible')
245            .attr(attr, $target.attr(attr))
246            .css({
247              position: 'absolute',
248              top: offset + 'px',
249              zIndex: -1000
250            })
251            .appendTo($scrollableElement);
252          $target.removeAttr(attr);
253          var complete = function () {
254            location.hash = element.hash;
255            $fakeAnchor.remove();
256            $target.attr(attr, element.hash.replace('#', ''));
257          };
258          if (Drupal.settings.bootstrap.anchorsSmoothScrolling) {
259            $scrollableElement.animate({ scrollTop: offset, avoidTransforms: true }, 400, complete);
260          }
261          else {
262            $scrollableElement.scrollTop(offset);
263            complete();
264          }
265        }
266      };
267    }
268  };
269
270  /**
271   * Tabledrag theming elements.
272   */
273  Drupal.theme.tableDragChangedMarker = function () {
274    return '<span class="tabledrag-changed glyphicon glyphicon-warning-sign text-warning"></span>';
275  };
276
277  Drupal.theme.tableDragChangedWarning = function () {
278    return '<div class="tabledrag-changed-warning alert alert-warning messages warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('Changes made in this table will not be saved until the form is submitted.') + '</div>';
279  };
280
281})(jQuery, Drupal);
282;

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.