PageSourceSearch

https://tanks-encyclopedia.com/wp-content/themes/te-custom-theme/c…/dropdowns/dropdowns.js?ver=1790825645

js tanks-encyclopedia.com collected 2026-10-02 03:26:57 UTC 11,513 bytes, 241 lines download raw bytes

1var te_dropdown = {
2    ClearAllDropdowns: function () {
3        const visibleDropdowns = $('.dropdown-toggle.show');
4        if(visibleDropdowns.length > 0) {
5            bootstrap.Dropdown.getOrCreateInstance(visibleDropdowns).hide();
6        }
7    }
8}
9
10{
11    const DropdownTimeoutMS = 500;
12    let DropdownTimeoutHandle;
13
14    let NavbarClickMode = false;
15    let DeviceIsHoverclicker = undefined;
16
17    /**
18     * Here is the general behavior of dropdowns:
19     * - The default is to open when the user hovers and close when the user exits after a timeout
20     * - If the user clicks any of the dropdowns, they will switch to being click-only
21     * - We detect if the user clicks immediately after hovering since that implies they are mobile and should be click-only
22     * - If you click or hover to open a dropdown that contains a nation page link, click again on the nation page words to navigate to the nation page
23     * - clicking on the dropdown arrows will always toggle the dropdown and not navigate you to the nation page
24     */
25
26    $(document).ready(function() {
27        window.addEventListener("scroll", te_dropdown.ClearAllDropdowns);
28
29        function HoverClicker_TemporaryClickEventHandler() {
30            DeviceIsHoverclicker = DeviceIsHoverclicker ?? true; //null coalesce just in case
31        }
32
33        function ExecuteIfNotHoverClickerDevice(action, elementWithHoverAction) {
34            if(DeviceIsHoverclicker === false) {
35                action();
36                return;
37            }
38            if(DeviceIsHoverclicker === undefined) {
39                elementWithHoverAction.addEventListener("click", HoverClicker_TemporaryClickEventHandler);
40                setTimeout(() => {
41                    if(!DeviceIsHoverclicker) {
42                        DeviceIsHoverclicker = false;
43                        action();
44                    }
45                    elementWithHoverAction.removeEventListener("click", HoverClicker_TemporaryClickEventHandler);
46                }, 1);
47            }
48        }
49
50        //For auto-closing the dropdowns when your mouse leaves all dropdown UI    
51        $(".te-navbar .dropdown, .te-navbar .dropdown-toggle, .te-navbar .nav-item").hover(
52            function (e) {
53                ExecuteIfNotHoverClickerDevice(() => {
54                    if(DropdownTimeoutHandle) {
55                        clearTimeout(DropdownTimeoutHandle);
56                    }
57                }, e.target);
58            },
59            function (e) {
60                ExecuteIfNotHoverClickerDevice(() => {
61                    if(DropdownTimeoutHandle) {
62                        clearTimeout(DropdownTimeoutHandle);
63                    }
64                    if(!NavbarClickMode) {
65                        DropdownTimeoutHandle = setTimeout(() => {
66                            te_dropdown.ClearAllDropdowns();
67                        }, DropdownTimeoutMS);
68                    }
69                }, e.target);
70            }
71        );
72
73        /*
74            The story of this additional click handler:
75            1. The dropdowns rely on padding-left to allow for
76               unclipped overflow content on subsequent dropdowns
77            2. This padding-left prevents clicks from triggering a
78               "hover out" event, thus not closing the dropdowns
79            3. Originally, this was solved with a simple
80               "pointer-events: none" style, with a reset on child
81               <li> elements.
82            4. However, this does not work in Safari
83               as the dropdowns were not scrollable, even with the
84               reset style in-place.
85            5. Tweaks were made the <li> elements such that it is
86               no longer possible for a user to click on the <ol>
87               element while attempting to access a dropdown value
88            6. Thus, the <ol> element itself can be made to close
89               the dropdowns for when a user clicks on the padding
90        */
91        $(".te-navbar .dropdown-menu").on("click", function (e) {
92            te_dropdown.ClearAllDropdowns();
93        });
94
95        //Split from the rest of the hover events to prevent closing the dropdown when you leave the nav-link but not the nav-item
96        $(".te-navbar .nav-link").on("mouseenter", function (e) {
97            ExecuteIfNotHoverClickerDevice(() => {
98                if(DropdownTimeoutHandle) {
99                    clearTimeout(DropdownTimeoutHandle);
100                }
101            }, e.target);
102        });
103
104        //For actually openning the dropdowns via mouse hover. Note: this is for both the top-level and the subdropdowns
105        $(".te-navbar .dropdown .dropdown-toggle").on("mouseenter", function (e) {
106            ExecuteIfNotHoverClickerDevice(() => {
107                //Hover actions should never close a dropdown
108                if(!NavbarClickMode && !$(e.target).hasClass("show")) {
109                    e.target.click();
110                    e.target.blur();
111                    NavbarClickMode = false;
112                }
113            }, e.target);
114        });
115
116        // close sibling dropdowns when hovered on an item with no children
117        $(".te-navbar .nav-item:not(.has-children)").on("mouseenter", function (e) {
118            ExecuteIfNotHoverClickerDevice(() => {
119                if(!NavbarClickMode) {
120                    //target could be the nav-link or nav-item for some reason...
121                    let openDropdownSibling
122                    if($(e.target).hasClass("nav-link")) {
123                        openDropdownSibling = $(e.target).parent().parent(".dropdown-menu.show").find(".dropdown-toggle.show");
124                    } else {
125                        openDropdownSibling = $(e.target).parent(".dropdown-menu.show").find(".dropdown-toggle.show");
126                    }
127                    if(openDropdownSibling.length > 0) bootstrap.Dropdown.getOrCreateInstance(openDropdownSibling).hide();
128                }
129            }, e.target);
130        });
131
132        //remove the drop-up styling so we can recalculate if that is even necessary
133        $(".te-navbar .dropdown .dropdown .dropdown-toggle").on("hidden.bs.dropdown", function (e) {
134            $(e.target).siblings(".dropdown-menu").toArray().forEach(s => {
135                s.style.maxHeight = "unset";
136                s.style.top = 0;
137            })
138        });
139
140        $(".te-navbar .dropdown .dropdown-toggle").on("click", function (e) {
141            NavbarClickMode = true; //this will trigger for both hovers and real clicks, but it gets reset to false during a hover
142        });
143
144        // Prevents closing the dropdown when we click between items
145        $(".te-navbar .dropdown .dropdown").on("click", function (e) {
146            // do not prevent default here, that removes the clicks on actual links
147            e.stopPropagation();
148        });
149
150        //Generic dropdown click behavior for desktop and mobile 
151        $(".te-navbar .dropdown .dropdown .dropdown-toggle").on("click", function (e) {
152            e.preventDefault();
153            e.stopPropagation();
154            const ParentsNeedingShown =
155                $(e.target)
156                .closest(".dropdown") //skip this element, we need to toggle instead of show
157                .parents(".dropdown") //all parent dropdowns excluding the dropdown we clicked
158                .children(".dropdown-toggle"); //the element that can actually toggle (the toggles are not direct descendants)
159            let previouslyOpen = $('.dropdown .dropdown .dropdown-toggle.show').not(ParentsNeedingShown).not($(e.target));
160
161            // we found that after navigating to deeper dropdown levels, lower level dropdowns would not immediately get hidden
162            // I believe this is because of a compatibility issue between jQuery's implicit looping system and Bootstrap
163            // This should only loop as many times as the number of dropdown levels present on the site, at max.
164            while(previouslyOpen.length > 0) {
165                bootstrap.Dropdown.getOrCreateInstance(previouslyOpen).hide();
166                previouslyOpen = $('.dropdown .dropdown .dropdown-toggle.show').not(ParentsNeedingShown).not($(e.target));
167            }
168            
169            bootstrap.Dropdown.getOrCreateInstance(ParentsNeedingShown).show();
170            //we used to have a call to toggle here on e.target. Some kind of event timing makes this unnecessary
171
172            HandleDropdownOverflowStyling();
173        });
174
175        $(window).on("resize", function (e) {
176            HandleDropdownOverflowStyling();
177            HandleDropdownOverflowStylingLevelOne();
178        });
179
180        $("#navbar-menus > li > button.dropdown-toggle").on("shown.bs.dropdown", function (e) {
181            HandleDropdownOverflowStylingLevelOne();
182        });
183
184        $("#navbar-menus > li > a.nav-link:not(*[href^='#'])").on("click", function (e) {
185            e.stopPropagation();
186        })
187
188        function HandleDropdownOverflowStylingLevelOne() {
189            $("#navbar-menus:not(.collapse) > li > ol.dropdown-menu.show").toArray().forEach((el) => {
190                let bounds = el.getBoundingClientRect();
191                let yPos = bounds.y;
192                let height = bounds.height;
193                let totalH = window.innerHeight;
194                let maxH = totalH - yPos;
195                //1/2 pixel because browsers aren't super precise, especially when zooming in or out
196                if(height + 0.5 >= maxH) {
197                    //proceed as dropdown with scroll (no dropup)
198                    el.style.maxHeight = `${maxH}px`;
199
200                    $(el).addClass("scrollable");
201                } else {
202                    el.style.maxHeight = "unset"; //reset so when you zoom in and out the bounding height updates
203                    $(el).removeClass("scrollable");
204                }
205            });
206        }
207
208        function HandleDropdownOverflowStyling() {
209            //#navbar-menus.collapse would indicate that the hamburgur dropdowns are being used
210            $("#navbar-menus:not(.collapse) .nav-item .nav-item ol.dropdown-menu.show").toArray().forEac
210h((el) => {
211                let bounds = el.getBoundingClientRect();
212                let yPos = bounds.y;
213                let height = bounds.height;
214                let totalH = window.innerHeight;
215                let maxH = totalH - yPos;
216                let dropUpDiff = height - yPos;
217                let dropDownDiff = totalH - yPos - height;
218                //1/2 pixel because browsers aren't super precise, especially when zooming in or out
219                if(height + 0.5 >= maxH) {
220                    //should we drop up instead of adding the scroll bar?
221                    if(dropUpDiff < dropDownDiff) {
222                        //attempt to dropup
223                        el.style.maxHeight = `${yPos}}px`;
224                        el.style.top = `calc(100% - ${height}px - 1px)`; //1px for borders
225                        if(dropUpDiff > 0.5) { //1/2 pixel because browsers aren't super precise, especially when zooming in or out
226                            $(el).addClass("scrollable");
227                        }
228                    } else {
229                        //proceed as dropdown with scroll
230                        el.style.maxHeight = `${maxH}px`;
231                        el.style.top = 0;
232
233                        $(el).addClass("scrollable");
234                    }
235                } else {
236                    $(el).removeClass("scrollable");
237                }
238            });
239        }
240    });
241}

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.