PageSourceSearch

https://static1.litmos.com/static/js/bootstrap3.4.1/bootstrap-fixes.js?v=182

js litmos.com collected 2026-09-24 08:52:03 UTC 12,885 bytes, 355 lines download raw bytes

1(function ($) {
2    'use strict';
3
4    // TABS CLASS DEFINITION
5    // ======================
6    // Usage:
7    // add attr data-tabs-keyboard-support="true" on html element with role=tablist
8    // OR
9    // $('[role=tablist]').tabsKeyboardSupport();
10
11    const Tabs = function (element, options) {
12        this.$element = $(element);
13        this.options = $.extend({}, options);
14        this.tabs = [];
15        this.firstTab = null;
16        this.lastTab = null;
17        this.activeTab = null;
18        this.init(element);
19    }
20
21    Tabs.prototype.init = function (element) {
22        this.tabs = [...element.querySelectorAll('[role=tab]')];
23
24        for (let i = 0; i < this.tabs.length; i++) {
25            const tab = this.tabs[i];
26            tab.addEventListener('keydown', this.onKeydown.bind(this));
27            tab.addEventListener('click', this.onClick.bind(this));
28
29            if (tab.classList.contains('active')) {
30                this.activeTab = tab;
31            }
32
33            if (!this.firstTab) {
34                this.firstTab = tab;
35            }
36            this.lastTab = tab;
37        }
38        if (this.activeTab) {
39            this.setSelectedTab(this.activeTab);
40        }
41    }
42
43    Tabs.prototype.setSelectedTab = function (currentTab) {
44        for (let i = 0; i < this.tabs.length; i++) {
45            const tab = this.tabs[i];
46            if (currentTab === tab) {
47                tab.classList.add('active');
48                tab.setAttribute('aria-selected', 'true');
49                tab.setAttribute('tabindex', '0');
50                this.activeTab = tab;
51            } else {
52                tab.classList.remove('active');
53                tab.setAttribute('aria-selected', 'false');
54                tab.setAttribute('tabindex', '-1');
55            }
56        }
57    }
58
59
60    Tabs.prototype.moveFocusToTab = function (currentTab) {
61        currentTab.focus();
62    }
63
64    Tabs.prototype.moveFocusToPreviousTab = function (currentTab) {
65        let index;
66
67        if (currentTab === this.firstTab) {
68            this.moveFocusToTab(this.lastTab);
69        } else {
70            index = this.tabs.indexOf(currentTab);
71            this.moveFocusToTab(this.tabs[index - 1]);
72        }
73    }
74
75    Tabs.prototype.moveFocusToNextTab = function (currentTab) {
76        let index;
77
78        if (currentTab === this.lastTab) {
79            this.moveFocusToTab(this.firstTab);
80        } else {
81            index = this.tabs.indexOf(currentTab);
82            this.moveFocusToTab(this.tabs[index + 1]);
83        }
84    }
85
86    /* EVENT HANDLERS */
87
88    Tabs.prototype.onKeydown = function (event) {
89        const target = event.currentTarget;
90        let flag = false;
91
92        switch (event.key) {
93            case 'ArrowLeft':
94                this.moveFocusToPreviousTab(target);
95                flag = true;
96                break;
97
98            case 'ArrowRight':
99                this.moveFocusToNextTab(target);
100                flag = true;
101                break;
102
103            case 'Home':
104                this.moveFocusToTab(this.firstTab);
105                flag = true;
106                break;
107
108            case 'End':
109                this.moveFocusToTab(this.lastTab);
110                flag = true;
111                break;
112
113            case ' ':
114                if (target.tagName.toLowerCase() === 'a') {
115                    event.preventDefault();
116                    event.currentTarget.click();
117                }
118                break;
119
120            default:
121                break;
122        }
123
124        if (flag) {
125            event.stopPropagation();
126            event.preventDefault();
127        }
128    }
129
130    Tabs.prototype.onClick = function (event) {
131        this.setSelectedTab(event.currentTarget);
132    }
133
134    // TABS PLUGIN DEFINITION
135    // =======================
136
137    function Plugin(option) {
138        var actionParams = Array.prototype.slice.call(arguments, 1);
139        return this.each(function () {
140            var $this = $(this);
141            var data = $this.data('bs.tabsKeyboardSupport');
142            var options = typeof option == 'object' && option;
143            if (!data) $this.data('bs.tabsKeyboardSupport', (data = new Tabs(this, options)));
144
145            var action = typeof option == 'string' && data[option];
146            if (action) action.apply(data, actionParams);
147        })
148    }
149
150    $.fn.tabsKeyboardSupport = Plugin;
151    $.fn.tabsKeyboardSupport.Constructor = Tabs;
152
153    $(function () {
154        const tabLists = [...document.querySelectorAll('[role=tablist][data-tabs-keyboard-support=true]')]
155            .filter((elm) => elm.querySelector('[role=tab]'));
156
157        $(tabLists).each(function () {
158            const $tabList = $(this);
159            Plugin.call($tabList);
160        });
161    });
162
163}(jQuery));
164
165$(function () {
166
167    $('.modal').on('show.bs.modal', function (e) {
168        $(this).attr('aria-hidden', 'false');
169    })
170    $('.modal').on('hide.bs.modal', function (e) {
171        $(this).attr('aria-hidden', 'true');
172    })
173
174    $(document).on('show.bs.modal', '.modal', function (e) {
175        var $target = $(this);
176        var $relatedElement = $(document.activeElement);
177        var modalData = $target.data('bs.modal');
178
179        if (!modalData.isShown) {
180            $target.one('hidden.bs.modal', function () {
181                if ($relatedElement[0] != document.activeElement && $relatedElement.is(':visible')) {
182                    $relatedElement.trigger('focus');
183                }
184            });
185        }
186    });
187
188    // Bootstrap 3.x erroneously adds the aria-expanded attribute to collapsible content.
189    // In the code below we fix it by removing the attribute manually after each collapsing/expanging.
190    // The issue is fixed in Bootstrap 4, so our fix can be removed after migration to Bootstrap 4.
191    $(document).on("shown.bs.collapse hidden.bs.collapse", function (event) {
192        $(event.target).removeAttr("aria-expanded");
193    });
194});
195
196(function ($) {
197    'use strict';
198
199    // tooltip a11y patch
200    // ======================
201    // fixes:
202    // the pointer can be moved over tooltip;
203    // tooltip can be dismissed by ESC
204    //
205    // new functionality:
206    // possibility to trigger tooltip from other element via param "relatedTargetId".
207    // for example trigger icon of tooltip is part of link but tooltip should be shown near icon
208    // Usage:
209    // data-related-target-id="other_element_id"
210    // <a href="#" id="link-id">Link text <span data-toggle="tooltip" data-related-target-id="link-id" title="Tooltip text">(i)</span></a>
211
212    $.fn.tooltip.Constructor.prototype.init = function (type, element, options) {
213        this.enabled = true
214        this.type = type
215        this.$element = $(element)
216        this.options = this.getOptions(options)
217        this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
218        this.inState = {click: false, hover: false, focus: false}
219
220        if (this.$element[0] instanceof document.constructor && !this.options.selector) {
221            throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
222        }
223
224        var triggers = this.options.trigger.split(' ')
225
226        for (var i = triggers.length; i--;) {
227            var trigger = triggers[i]
228            // relatedTargetId and selector cannot be used at the same time
229            var isSelector = !!this.options.selector;
230            var relatedTarget = this.options.relatedTargetId && document.getElementById(this.options.relatedTargetId);
231
232            if (!isSelector) {
233                this.relatedTarget = relatedTarget;
234            }
235
236            if (trigger == 'click') {
237                this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
238            } else if (trigger == 'hover') {
239                this.$element.on('mouseenter.' + this.type, this.options.selector, $.proxy(this.mouseenterHandler, this))
240                this.$element.on('mouseleave.' + this.type, this.options.selector, $.proxy(this.mouseleaveHandler, this))
241
242                if (this.relatedTarget) {
243                    $(this.relatedTarget).on('mouseover.' + this.type, this.options.selector, $.proxy(this.mouseenterHandler, this))
244                    $(this.relatedTarget).on('mouseout.' + this.type, this.options.selector, $.proxy(this.mouseleaveHandler, this))
245                }
246            } else if (trigger == 'focus') {
247                this.$element.on('focusin.' + this.type, this.options.selector, $.proxy(this.focusinHandler, this))
248                this.$element.on('focusout.' + this.type, this.options.selector, $.proxy(this.focusoutHandler, this))
249
250                if (this.relatedTarget) {
251                    $(this.relatedTarget).on('focusin.' + this.type, this.options.selector, $.proxy(this.focusinHandler, this))
252                    $(this.relatedTarget).on('focusout.' + this.type, this.options.selector, $.proxy(this.focusoutHandler, this))
253                }
254            }
255        }
256
257        if (this.relatedTarget) {
258            $(this.relatedTarget).data('bs.' + this.type, this);
259
260            this.$element.on('inserted.bs.' + this.type, $.proxy(function () {
261                var tipId = this.tip().attr('id');
262                $(this.relatedTarget).attr('aria-describedby', tipI
262d);
263            }, this));
264
265            this.$element.on('hidden.bs.' + this.type, $.proxy(function () {
266                $(this.relatedTarget).removeAttr('aria-describedby');
267            }, this));
268        }
269
270        this.options.selector ?
271            (this._options = $.extend({}, this.options, {trigger: 'manual', selector: ''})) :
272            this.fixTitle()
273    }
274
275    $.fn.tooltip.Constructor.prototype.mouseenterHandler = function (e) {
276        var self = this.getInstance(e);
277
278        if (self.isInStateTrue()) {
279            clearTimeout(self.timeoutMouse);
280            return;
281        }
282
283        self.inState['hover'] = true;
284        self.enter(self);
285        self.tip().off('.' + this.type);
286        self.tip().on('mouseenter.' + this.type, $.proxy(this.mouseenterHandler, this))
287        self.tip().on('mouseleave.' + this.type, $.proxy(this.mouseleaveHandler, this))
288    }
289
290    $.fn.tooltip.Constructor.prototype.mouseleaveHandler = function (e) {
291        var self = this.getInstance(e);
292
293        clearTimeout(self.timeoutMouse);
294        self.timeoutMouse = setTimeout(function () {
295            self.inState['hover'] = false;
296            self.leave(self);
297        }, 100);
298    }
299
300    $.fn.tooltip.Constructor.prototype.focusinHandler = function (e) {
301        var self = this.getInstance(e);
302        self.inState['focus'] = true;
303        self.enter(self);
304        self.escape();
305    }
306
307    $.fn.tooltip.Constructor.prototype.focusoutHandler = function (e) {
308        var self = this.getInstance(e);
309        self.inState['focus'] = false;
310        self.leave(self);
311    }
312
313    $.fn.tooltip.Constructor.prototype.escape = function () {
314        var $activeElement = $(document.activeElement);
315        $activeElement.off('keydown.dismiss.bs.' + this.type);
316        $activeElement.on('keydown.dismiss.bs.' + this.type, $.proxy(function (e) {
317            if (e.which == 27 && this.tip().hasClass('in')) {
318                this.inState['focus'] = false;
319                this.leave(this);
320            }
321        }, this))
322    }
323
324    $.fn.tooltip.Constructor.prototype.getInstance = function (obj) {
325        var self = obj instanceof this.constructor ?
326            obj : $(obj.currentTarget).data('bs.' + this.type)
327
328        if (!self) {
329            self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
330            $(obj.currentTarget).data('bs.' + this.type, self)
331        }
332        return self;
333    }
334
335    $.fn.tooltip.Constructor.prototype.destroy = function () {
336        var that = this;
337        clearTimeout(this.timeout);
338        clearTimeout(self.timeoutMouse);
339        this.hide(function () {
340            that.$element.off('.' + that.type).removeData('bs.' + that.type);
341            if (that.relatedTarget) {
342                $(that.relatedTarget).off('.' + that.type).removeData('bs.' + that.type);
343                that.relatedTarget = null;
344            }
345            if (that.$tip) {
346                that.$tip.detach()
347            }
348            that.$tip = null
349            that.$arrow = null
350            that.$viewport = null
351            that.$element = null
352        })
353    }
354
355}(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.