@@ -111,103 +111,7 @@ function initializeKeyboardShortcuts() {
111111 } ) ;
112112}
113113
114- // Search functionality (basic)
115- function initializeSearch ( ) {
116- // Add search input to header if it doesn't exist
117- const controls = document . querySelector ( '.controls' ) ;
118- if ( controls && ! document . getElementById ( 'search-input' ) ) {
119- const searchGroup = document . createElement ( 'div' ) ;
120- searchGroup . className = 'control-group' ;
121-
122- const searchLabel = document . createElement ( 'label' ) ;
123- searchLabel . setAttribute ( 'for' , 'search-input' ) ;
124- searchLabel . textContent = 'Search:' ;
125-
126- const searchInput = document . createElement ( 'input' ) ;
127- searchInput . type = 'text' ;
128- searchInput . id = 'search-input' ;
129- searchInput . placeholder = 'Search messages...' ;
130- searchInput . style . padding = '0.5rem' ;
131- searchInput . style . border = '1px solid var(--border-color)' ;
132- searchInput . style . borderRadius = '0.375rem' ;
133- searchInput . style . backgroundColor = 'var(--bg-primary)' ;
134- searchInput . style . color = 'var(--text-primary)' ;
135- searchInput . style . fontSize = '0.875rem' ;
136- searchInput . style . minWidth = '200px' ;
137-
138- searchGroup . appendChild ( searchLabel ) ;
139- searchGroup . appendChild ( searchInput ) ;
140- controls . insertBefore ( searchGroup , controls . lastElementChild ) ;
141-
142- // Add search functionality
143- let searchTimeout ;
144- searchInput . addEventListener ( 'input' , function ( e ) {
145- clearTimeout ( searchTimeout ) ;
146- searchTimeout = setTimeout ( ( ) => {
147- performSearch ( e . target . value ) ;
148- } , 300 ) ;
149- } ) ;
150- }
151- }
152-
153- function performSearch ( searchTerm ) {
154- const messages = document . querySelectorAll ( '.message-content' ) ;
155- const highlights = document . querySelectorAll ( '.search-highlight' ) ;
156-
157- // Clear previous highlights
158- highlights . forEach ( highlight => {
159- const parent = highlight . parentNode ;
160- parent . replaceChild ( document . createTextNode ( highlight . textContent ) , highlight ) ;
161- parent . normalize ( ) ;
162- } ) ;
163-
164- if ( ! searchTerm . trim ( ) ) {
165- return ;
166- }
167-
168- const regex = new RegExp ( `(${ escapeRegExp ( searchTerm ) } )` , 'gi' ) ;
169-
170- messages . forEach ( messageContent => {
171- const textNodes = getTextNodes ( messageContent ) ;
172- textNodes . forEach ( node => {
173- if ( regex . test ( node . textContent ) ) {
174- const parent = node . parentNode ;
175- const highlighted = node . textContent . replace ( regex , '<mark class="search-highlight">$1</mark>' ) ;
176- const wrapper = document . createElement ( 'span' ) ;
177- wrapper . innerHTML = highlighted ;
178- parent . replaceChild ( wrapper , node ) ;
179-
180- // Open the containing details if closed
181- let detailsParent = parent . closest ( 'details' ) ;
182- while ( detailsParent ) {
183- detailsParent . setAttribute ( 'open' , '' ) ;
184- detailsParent = detailsParent . parentElement . closest ( 'details' ) ;
185- }
186- }
187- } ) ;
188- } ) ;
189- }
190-
191- function getTextNodes ( element ) {
192- const textNodes = [ ] ;
193- const walker = document . createTreeWalker (
194- element ,
195- NodeFilter . SHOW_TEXT ,
196- null ,
197- false
198- ) ;
199-
200- let node ;
201- while ( node = walker . nextNode ( ) ) {
202- textNodes . push ( node ) ;
203- }
204-
205- return textNodes ;
206- }
207114
208- function escapeRegExp ( string ) {
209- return string . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ;
210- }
211115
212116// Code highlighting (basic syntax highlighting)
213117function initializeCodeHighlighting ( ) {
@@ -274,39 +178,44 @@ function initializePerformanceMonitoring() {
274178}
275179
276180// Message expand/collapse functionality
277- function toggleMessageExpand ( clickedElement ) {
181+ function expandMessage ( clickedElement ) {
278182 const messageContent = clickedElement . closest ( '.message-content' ) ;
279183 const previewShort = messageContent . querySelector ( '.message-preview-short' ) ;
280184 const contentFull = messageContent . querySelector ( '.message-content-full' ) ;
281185 const contentExpanded = messageContent . querySelector ( '.message-content-expanded' ) ;
282186
283- if ( clickedElement . classList . contains ( 'message-preview-short' ) ) {
284- // Expanding - hide preview, show full content
285- if ( previewShort ) previewShort . style . display = 'none' ;
286- if ( contentFull ) contentFull . style . display = 'block' ;
287- if ( contentExpanded ) contentExpanded . style . display = 'block' ;
288-
289- // Smooth scroll to keep the content in view
290- setTimeout ( ( ) => {
291- messageContent . scrollIntoView ( {
292- behavior : 'smooth' ,
293- block : 'nearest'
294- } ) ;
295- } , 100 ) ;
296- } else if ( clickedElement . classList . contains ( 'message-content-full' ) || clickedElement . classList . contains ( 'message-content-expanded' ) ) {
297- // Collapsing - show preview, hide full content
298- if ( contentFull ) contentFull . style . display = 'none' ;
299- if ( contentExpanded ) contentExpanded . style . display = 'none' ;
300- if ( previewShort ) previewShort . style . display = 'block' ;
301-
302- // Smooth scroll to keep the content in view
303- setTimeout ( ( ) => {
304- messageContent . scrollIntoView ( {
305- behavior : 'smooth' ,
306- block : 'nearest'
307- } ) ;
308- } , 100 ) ;
309- }
187+ // Expanding - hide preview, show full content
188+ if ( previewShort ) previewShort . style . display = 'none' ;
189+ if ( contentFull ) contentFull . style . display = 'block' ;
190+ if ( contentExpanded ) contentExpanded . style . display = 'block' ;
191+
192+ // Smooth scroll to keep the content in view
193+ setTimeout ( ( ) => {
194+ messageContent . scrollIntoView ( {
195+ behavior : 'smooth' ,
196+ block : 'nearest'
197+ } ) ;
198+ } , 100 ) ;
199+ }
200+
201+ function collapseMessage ( clickedElement ) {
202+ const messageContent = clickedElement . closest ( '.message-content' ) ;
203+ const previewShort = messageContent . querySelector ( '.message-preview-short' ) ;
204+ const contentFull = messageContent . querySelector ( '.message-content-full' ) ;
205+ const contentExpanded = messageContent . querySelector ( '.message-content-expanded' ) ;
206+
207+ // Collapsing - show preview, hide full content
208+ if ( contentFull ) contentFull . style . display = 'none' ;
209+ if ( contentExpanded ) contentExpanded . style . display = 'none' ;
210+ if ( previewShort ) previewShort . style . display = 'block' ;
211+
212+ // Smooth scroll to keep the content in view
213+ setTimeout ( ( ) => {
214+ messageContent . scrollIntoView ( {
215+ behavior : 'smooth' ,
216+ block : 'nearest'
217+ } ) ;
218+ } , 100 ) ;
310219}
311220
312221
@@ -316,7 +225,6 @@ document.addEventListener('DOMContentLoaded', function() {
316225 initializeTheme ( ) ;
317226 initializeFoldouts ( ) ;
318227 initializeKeyboardShortcuts ( ) ;
319- initializeSearch ( ) ;
320228 initializeCodeHighlighting ( ) ;
321229 initializePerformanceMonitoring ( ) ;
322230
0 commit comments