PageSourceSearch

https://pupwife.com/projects/chatroom/scripts/mobileSidebars.js

js pupwife.com collected 2026-09-30 15:07:22 UTC 7,524 bytes, 230 lines download raw bytes

1/**
2 * Mobile Sidebar System
3 * Handles slideout sidebars for mobile devices
4 */
5
6window.ChatroomMobileSidebars = (function() {
7    'use strict';
8
9    let leftSidebarOpen = false;
10    let rightSidebarOpen = false;
11
12    /**
13     * Initialize mobile sidebar system
14     */
15    function init() {
16        if (!isMobile()) {
17            return; // Only initialize on mobile
18        }
19
20        createToggleButtons();
21        setupEventListeners();
22        setupOverlay();
23    }
24
25    /**
26     * Check if device is mobile
27     */
28    function isMobile() {
29        return window.innerWidth <= 768;
30    }
31
32    /**
33     * Create toggle buttons for sidebars
34     */
35    function createToggleButtons() {
36        // Left sidebar toggle (for navigation + channels)
37        const leftToggle = document.createElement('button');
38        leftToggle.className = 'mobile-sidebar-toggle mobile-sidebar-toggle-left';
39        leftToggle.innerHTML = '☰';
40        leftToggle.title = 'Open Navigation';
41        leftToggle.id = 'mobile-sidebar-toggle-left';
42        document.body.appendChild(leftToggle);
43
44        // Right sidebar toggle (for members)
45        const rightToggle = document.createElement('button');
46        rightToggle.className = 'mobile-sidebar-toggle mobile-sidebar-toggle-right';
47        rightToggle.innerHTML = '👥';
48        rightToggle.title = 'Open Members';
49        rightToggle.id = 'mobile-sidebar-toggle-right';
50        document.body.appendChild(rightToggle);
51    }
52
53    /**
54     * Setup event listeners
55     */
56    function setupEventListeners() {
57        const leftToggle = document.getElementById('mobile-sidebar-toggle-left');
58        const rightToggle = document.getElementById('mobile-sidebar-toggle-right');
59        const overlay = document.getElementById('mobile-sidebar-overlay');
60        
61        const navColumn = document.querySelector('.navigation-column');
62        const channelsColumn = document.querySelector('.channels-column');
63        const membersColumn = document.querySelector('.members-column');
64
65        // Left toggle - opens navigation and channels
66        if (leftToggle) {
67            leftToggle.addEventListener('click', (e) => {
68                e.stopPropagation();
69                toggleLeftSidebar();
70            });
71        }
72
73        // Right toggle - opens members
74        if (rightToggle) {
75            rightToggle.addEventListener('click', (e) => {
76                e.stopPropagation();
77                toggleRightSidebar();
78            });
79        }
80
81        // Overlay click - closes all sidebars
82        if (overlay) {
83            overlay.addEventListener('click', () => {
84                closeAllSidebars();
85            });
86        }
87
88        // Close sidebars when clicking outside
89        document.addEventListener('click', (e) => {
90            if (leftSidebarOpen || rightSidebarOpen) {
91                const isClickInsideLeft = navColumn?.contains(e.target) || 
92                                         channelsColumn?.contains(e.target) ||
93                                         leftToggle?.contains(e.target);
94                const isClickInsideRight = membersColumn?.contains(e.target) ||
95                                          rightToggle?.contains(e.target);
96                
97                if (!isClickInsideLeft && !isClickInsideRight) {
98                    closeAllSidebars();
99                }
100            }
101        });
102
103        // Handle window resize
104        let resizeTimeout;
105        window.addEventListener('resize', () => {
106            clearTimeout(resizeTimeout);
107            resizeTimeout = setTimeout(() => {
108                if (!isMobile()) {
109                    closeAllSidebars();
110                    // Hide toggle buttons on desktop
111                    if (leftToggle) leftToggle.style.display = 'none';
112                    if (rightToggle) rightToggle.style.display = 'none';
113                } else {
114                    // Show toggle buttons on mobile
115                    if (leftToggle) leftToggle.style.display = 'flex';
116                    if (rightToggle) rightToggle.style.display = 'flex';
117                }
118            }, 100);
119        });
120
121        // Close sidebars on escape key
122        document.addEventListener('keydown', (e) => {
123            if (e.key === 'Escape') {
124                closeAllSidebars();
125            }
126        });
127    }
128
129    /**
130     * Setup overlay
131     */
132    function setupOverlay() {
133        const overlay = document.createElement('div');
134        overlay.id = 'mobile-sidebar-overlay';
135        overlay.className = 'mobile-sidebar-overlay';
136        document.body.appendChild(overlay);
137    }
138
139    /**
140     * Toggle left sidebar (navigation + channels)
141     */
142    function toggleLeftSidebar() {
143        const navColumn = document.querySelector('.navigation-column');
144        const channelsColumn = document.querySelector('.channels-column');
145        const overlay = document.getElementById('mobile-sidebar-overlay');
146
147        leftSidebarOpen = !leftSidebarOpen;
148
149        if (leftSidebarOpen) {
150            // Close right sidebar if open
151            if (rightSidebarOpen) {
152                toggleRightSidebar();
153            }
154            
155            navColumn?.classList.add('mobile-open');
156            channelsColumn?.classList.add('mobile-open');
157            overlay?.classList.add('active');
158            document.body.style.overflow = 'hidden';
159        } else {
160            navColumn?.classList.remove('mobile-open');
161            channelsColumn?.classList.remove('mobile-open');
162            if (!rightSidebarOpen) {
163                overlay?.classList.remove('active');
164                document.body.style.overflow = '';
165            }
166        }
167    }
168
169    /**
170     * Toggle right sidebar (members)
171     */
172    function toggleRightSidebar() {
173        const membersColumn = document.querySelector('.members-column');
174        const overlay = document.getElementById('mobile-sidebar-overlay');
175
176        rightSidebarOpen = !rightSidebarOpen;
177
178        if (rightSidebarOpen) {
179            // Close left sidebar if open
180            if (leftSidebarOpen) {
181                toggleLeftSidebar();
182            }
183            
184            membersColumn?.classList.add('mobile-open');
185            overlay?.classList.add('active');
186            document.body.style.overflow = 'hidden';
187        } else {
188            membersColumn?.classList.remove('mobile-open');
189            if (!leftSidebarOpen) {
190                overlay?.classList.remove('active');
191                document.body.style.overflow = '';
192            }
193        }
194    }
195
196    /**
197     * Close all sidebars
198     */
199    function closeAllSidebars() {
200        if (leftSidebarOpen) {
201            toggleLeftSidebar();
202        }
203        if (rightSidebarOpen) {
204            toggleRightSidebar();
205        }
206    }
207
208    // Initialize on load
209    if (document.readyState === 'loading') {
210        document.addEventListener('DOMContentLoaded', init);
211    } else {
212        init();
213    }
214
215    // Re-initialize on resize to handle orientation changes
216    window.addEventListener('resize', () => {
217        if (isMobile() && !document.getElementById('mobile-sidebar-toggle-left')) {
218            init();
219        }
220    });
221
222    return {
223        init,
224        toggleLeftSidebar,
225        toggleRightSidebar,
226        closeAllSidebars,
227        isMobile
228    };
229})();
230

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.