PageSourceSearch

https://www.sebi.gov.in/js/webslidemenu1.js

js sebi.gov.in collected 2026-09-24 08:37:21 UTC 13,749 bytes, 309 lines download raw bytes

1$(function() {
2    var isMobileEscaping = false;
3
4        // ==========================================================================
5    // 0. DYNAMIC HAMBURGER TAG TRANSFORMATION ENGINE (GLOBAL COMPLIANCE FIX)
6    // ==========================================================================
7    function transformHamburgerToTrueButton() {
8        var $hamburger = $('#wsnavtoggle');
9        
10        // If it is currently an anchor tag (<a>), swap it to a true <button>
11        if ($hamburger.length > 0 && $hamburger.is('a')) {
12            var $trueButton = $('<button>', {
13                'id': $hamburger.attr('id'),
14                'class': $hamburger.attr('class'),
15                'aria-expanded': $hamburger.attr('aria-expanded') || 'false',
16                'type': 'button'
17            });
18
19            // Move the inner structural contents (like the <span> elements) safely over
20            $trueButton.html($hamburger.html());
21
22            // Swap out the nodes inside the live DOM tree framework
23            $hamburger.replaceWith($trueButton);
24        }
25    }
26
27    // Run transformation loop instantly on file compilation entry phase
28    transformHamburgerToTrueButton();
29
30
31    // ==========================================================================
32    // 1. HAMBURGER TOGGLE & OVERLAY MANAGEMENT
33    // ==========================================================================
34    $(document).off('click', '#wsnavtoggle').on('click', '#wsnavtoggle', function(e) {
35        e.preventDefault();
36        $('.wsmenucontainer').toggleClass('wsoffcanvasopener');
37        var isOpen = $('.wsmenucontainer').hasClass('wsoffcanvasopener');
38        $(this).attr('aria-expanded', isOpen ? 'true' : 'false');
39        
40        if (isOpen) {
41            setTimeout(function() {
42                $('#wsnavtoggle').focus(); 
43            }, 150); 
44        } else {
45            setTimeout(function() {
46                $('#wsnavtoggle').focus();
47                initializeDynamicMobilePassThrough();
48            }, 50);
49        }
50    });
51
52    $(document).off('click', '.overlapblackbg').on('click', '.overlapblackbg', function() {
53        $('.wsmenucontainer').removeClass('wsoffcanvasopener');
54        $('#wsnavtoggle').attr('aria-expanded', 'false').focus();
55    });
56
57
58
59    // ==========================================================================
60    // 2. ACCESSIBLE BUTTON INJECTIONS (FIXED POSITION BETWEEN LINK AND UL)
61    // ==========================================================================
62    $('.wsmenu-list > li').has('.wsmenu-submenu, .megamenu').each(function() {
63        var $li = $(this);
64        var $anchor = $li.find('> a');
65        var labelText = $anchor.text().trim();
66        
67        if (!$li.find('> .wsmenu-click').length) {
68            $('<button class="wsmenu-click" type="button" aria-expanded="false" aria-label="More ' + labelText + '"><i class="wsmenu-arrow fa fa-angle-down"></i></button>')
69                .insertAfter($anchor);
70        }
71    });
72
73    $('.wsmenu-list > li > ul > li').has('.wsmenu-submenu-sub, .wsmenu-submenu-sub-sub').each(function() {
74        var $li = $(this);
75        var $anchor = $li.find('> a');
76        var labelText = $anchor.text().trim();
77        
78        if (!$li.find('> .wsmenu-click02').length) {
79            $('<button class="wsmenu-click02" type="button" aria-expanded="false" aria-label="More ' + labelText + '"><i class="wsmenu-arrow fa fa-angle-down"></i></button>')
80                .insertAfter($anchor);
81        }
82    });
83
84        // ==========================================================================
85    // 3. LEVEL 1 TOGGLE CONTROLLERS (CLEAN SLIDE INTERACTION)
86    // ==========================================================================
87    $('.wsmenu-click').off('click').click(function(e) {
88        e.preventDefault();
89        e.stopPropagation();
90
91        var $button = $(this);
92        var $parentLi = $button.closest('li');
93        var $dropdownMenu = $parentLi.find('> .wsmenu-submenu, > .megamenu');
94        var isCurrentlyOpen = $button.attr('aria-expanded') === 'true';
95
96        if (!isMobileEscaping) {
97            $('.wsmenu-click').not($button).attr('aria-expanded', 'false').removeClass('ws-activearrow');
98            $('.wsmenu-submenu, .megamenu').not($dropdownMenu).slideUp('slow');
99            $('.wsmenu-list > li').not($parentLi).removeClass('sfHover');
100        }
101
102        if (isCurrentlyOpen) {
103            $button.attr('aria-expanded', 'false').removeClass('ws-activearrow');
104            $dropdownMenu.slideUp('slow');
105            $parentLi.removeClass('sfHover');
106        } else {
107            $button.attr('aria-expanded', 'true').addClass('ws-activearrow');
108            $dropdownMenu.slideDown('slow');
109            $parentLi.addClass('sfHover');
110        }
111    });
112
113    // ==========================================================================
114    // 4. LEVEL 2 TOGGLE CONTROLLERS (CLEAN SLIDE INTERACTION)
115    // ==========================================================================
116    $('.wsmenu-click02').off('click').click(function(e) {
117        e.preventDefault();
118        e.stopPropagation();
119
120        var $button = $(this);
121        var $parentLi = $button.closest('li');
122        var $subChildUl = $parentLi.find('> .wsmenu-submenu-sub, > .wsmenu-submenu-sub-sub');
123        var isCurrentlyOpen = $button.attr('aria-expanded') === 'true';
124
125        if (isCurrentlyOpen) {
126            $button.attr('aria-expanded', 'false').children('.wsmenu-arrow').removeClass('wsmenu-rotate');
127            $subChildUl.slideUp('slow');
128        } else {
129            $button.attr('aria-expanded', 'true').children('.wsmenu-arrow').addClass('wsmenu-rotate');
130            $subChildUl.slideDown('slow');
131        }
132    });
133
134
135
136
137    // ==========================================================================
138    // 5. UNIFIED MOBILE ESCAPE CONTROLLER LOGIC (FIXED SINGLE-LEVEL BUTTON FOCUS)
139    // ==========================================================================
140    $('.wsmenu-list').off('keydown').on('keydown', function(event) {
141        if (window.innerWidth < 768 && (event.key === 'Escape' || event.key === 'Esc')) {
142            var $activeElement = $(document.activeElement);
143            
144            // ------------------------------------------------------------------
145            // TIER 1: Focus is deep inside an Inner Level Submenu (e.g., "The Board")
146            // ------------------------------------------------------------------
147            if ($activeElement.closest('.wsmenu-submenu-sub, .sub_child2, .wsmenu-submenu-sub-sub').length > 0) {
148                event.preventDefault();
149                event.stopPropagation();
150                
151                var $parentFolderLi = $activeElement.closest('.has-accessible-submenu');
152                var $parentFolderBtn = $parentFolderLi.find('> button.wsmenu-click02, > .wsmenu-click02');
153
154                if ($parentFolderBtn.attr('aria-expanded') === 'true') {
155                    isMobileEscaping = true;
156
157                    $parentFolderBtn.trigger('click');
158                    $parentFolderBtn.attr('aria-expanded', 'false');
159                    $parentFolderBtn.children('.wsmenu-arrow').removeClass('wsmenu-rotate');
160                    
161                    // Focus moves onto the "About SEBI" toggle button item row
162                    $parentFolderBtn.focus();
163
164                    setTimeout(function() {
165                        isMobileEscaping = false;
166                    }, 400);
167                }
168                return false; 
169            } 
170            
171            // ------------------------------------------------------------------
172            // TIER 2: Focus is on the Main Submenu folder level (e.g., Single-Level Dropdowns)
173            // ------------------------------------------------------------------
174            if ($activeElement.closest('.wsmenu-submenu, .megamenu').length > 0) {
175                event.preventDefault();
176                event.stopPropagation();
177                
178                var $rootLi = $activeElement.closest('.wsmenu-list > li, .sf-menu > li');
179                var $rootToggleBtn = $rootLi.find('> button.wsmenu-click, > .wsmenu-click');
180
181                if ($rootToggleBtn.attr('aria-expanded') === 'true') {
182                    isMobileEscaping = true;
183
184                    $rootToggleBtn.trigger('click');
185                    $rootToggleBtn.attr('aria-expanded', 'false');
186                    $rootToggleBtn.removeClass('ws-activearrow');
187                    
188                    // Move focus directly and reliably back to the toggle button
189                    $rootToggleBtn.focus();
190
191                    setTimeout(function() {
192                        isMobileEscaping = false;
193                    }, 400);
194                }
195                return false;
196            }
197        }
198    });
199
200    // ==========================================================================
201    // 6. MOBILE NAVIGATION ARIA KEYBOARD FOCUS TRAP CONFIGURATION (STABILIZED)
202    // ==========================================================================
203    $(document).off('keydown.focustrap').on('keydown.focustrap', function(event) {
204        if (window.innerWidth < 768 && $('.wsmenucontainer').hasClass('wsoffcanvasopener')) {
205            
206            if (event.key === 'Tab' || event.keyCode === 9) {
207                var $menuContainer = $('.wsmenu, .wsmenu-list');
208                
209                // Get all interior menu links and active visible toggle arrows
210                var $focusableElements = $menuContainer.find('a[href], button.wsmenu-click, button.wsmenu-click02').filter(':visible');
211                var $closeToggleBtn = $('#wsnavtoggle').filter(':visible');
212                
213                var elementsArray = [];
214                
215                // Establish close button wrapper coordinates at position 0
216                if ($closeToggleBtn.length > 0) {
217                    elementsArray.push($closeToggleBtn[0]);
218                }
219                
220                $focusableElements.each(function() {
221                    elementsArray.push(this);
222                });
223
224                if (elementsArray.length === 0) return;
225
226                var firstBoundary = elementsArray[0];
227                var lastBoundary = elementsArray[elementsArray.length - 1];
228
229                // Backward Trap Cycle (Shift + Tab)
230                if (event.shiftKey) {
231                    if (document.activeElement === firstBoundary) {
232                        event.preventDefault();
233                        $(lastBoundary).focus(); 
234                    }
235                } 
236                // Forward Trap Cycle (Tab)
237                else {
238                    if (document.activeElement === lastBoundary) {
239                        event.preventDefault();
240                        $(firstBoundary).focus(); 
241                    }
242                }
243            }
244        }
245    });
246
247
248    // ==========================================================================
249    // 7. RESPONSIVE ARIA-HIDDEN SWAPPER ENGINE (DESKTOP VS MOBILE TOGGLES)
250    // ==========================================================================
251    function syncResponsiveAriaStates() {
252        var isMobile = window.innerWidth < 768;
253
254        if (isMobile) {
255            // Mobile View Settings:
256            // 1. Hide the desktop toggle buttons from screen readers entirely
257            $('.submenu-toggle, #sebi-btn').attr({
258                'aria-hidden': 'true',
259                'tabindex': '-1' // Prevents accidental keyboard focus
260            });
261
262            // 2. Expose mobile framework toggle arrows safely to screen readers
263            $('.wsmenu-click, .wsmenu-click02').attr({
264                'aria-hidden': 'false',
265                'tabindex': '0'
266            });
267        } else {
268            // Desktop View Settings:
269            // 1. Expose desktop specific buttons back to standard access matrices
270            $('.submenu-toggle, #sebi-btn').attr({
271                'aria-hidden': 'false',
272                'tabindex': '0'
273            });
274
275            // 2. Hide mobile click containers entirely on desktop monitors
276            $('.wsmenu-click, .wsmenu-click02').attr({
277                'aria-hidden': 'true',
278                'tabindex': '-1'
279            });
280        }
281    }
282
283    // Run structural calculations instantly on page load initialization
284    syncResponsiveAriaStates();
285
286    // Bind an event listener to keep properties aligned if a device is flipped or resized
287    $(window).on('resize', function() {
288        syncResponsiveAriaStates();
289    });
290
291    // ==========================================================================
292    // 8. GLOBAL MOBILE ACCESSIBILITY SKIP-TAB ENGINE (CORRECTED DELEGATION)
293    // ==========================================================================
294    function setInitialMobileFocus() {
295        if (window.innerWidth < 768) {
296            // Find the link containing the Azadi ka Amrit Mahotsav image asset target
297            var $azadiLogoLink = $('a[title="Azadi ka Amrit Mahotsav"], a:has(img[src*="azadi-logo"])').first();
298            
299            if ($azadiLogoLink.length > 0) {
300                // Instantly force focus onto the image link on page load
301                $azadiLogoLink.focus();
302            }
303        }
304    }
305
306    // Execute the focus redirection immediately on script execution lifecycle entry
307    setInitialMobileFocus();
308
309});

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.