@@ -174,7 +174,6 @@ class App {
174174 this . fileList = document . getElementById ( 'fileList' ) ;
175175 this . resultsSection = document . getElementById ( 'resultsSection' ) ;
176176 this . resultsContainer = document . getElementById ( 'resultsContainer' ) ;
177- this . clearBtn = document . getElementById ( 'clearBtn' ) ;
178177
179178 // Check if elements exist
180179 if ( ! this . uploadArea || ! this . fileInput ) {
@@ -184,30 +183,34 @@ class App {
184183 }
185184
186185 setupEventListeners ( ) {
187- // Click to upload - ensure it works even if upload-content is clicked
186+ // Click to upload - use label approach for better browser compatibility
187+ // The label wraps the file input, so clicking anywhere on upload area triggers it
188+ const fileInputLabel = this . uploadArea . querySelector ( '.file-input-label' ) ;
189+ if ( fileInputLabel ) {
190+ // Make label cover entire upload area
191+ fileInputLabel . style . position = 'absolute' ;
192+ fileInputLabel . style . top = '0' ;
193+ fileInputLabel . style . left = '0' ;
194+ fileInputLabel . style . width = '100%' ;
195+ fileInputLabel . style . height = '100%' ;
196+ fileInputLabel . style . cursor = 'pointer' ;
197+ fileInputLabel . style . zIndex = '1' ;
198+ }
199+
200+ // Also handle clicks on upload area as fallback
188201 this . uploadArea . addEventListener ( 'click' , ( e ) => {
189202 // Don't trigger if clicking on remove button or other interactive elements
190203 if ( e . target . closest ( '.remove-file' ) || e . target . closest ( '.btn' ) ) {
191204 return ;
192205 }
193- // Trigger file input click
194- if ( this . fileInput ) {
195- e . preventDefault ( ) ;
196- e . stopPropagation ( ) ;
197- this . fileInput . click ( ) ;
206+ // Trigger file input click if label didn't work
207+ if ( this . fileInput && e . target !== this . fileInput && ! e . target . closest ( 'label' ) ) {
208+ // Use setTimeout for better compatibility
209+ setTimeout ( ( ) => {
210+ this . fileInput . click ( ) ;
211+ } , 0 ) ;
198212 }
199213 } ) ;
200-
201- // Also make upload-content clickable (bypass pointer-events: none)
202- const uploadContent = this . uploadArea . querySelector ( '.upload-content' ) ;
203- if ( uploadContent ) {
204- uploadContent . addEventListener ( 'click' , ( e ) => {
205- e . stopPropagation ( ) ;
206- if ( this . fileInput ) {
207- this . fileInput . click ( ) ;
208- }
209- } ) ;
210- }
211214
212215 // Drag and drop
213216 this . uploadArea . addEventListener ( 'dragover' , ( e ) => {
@@ -229,11 +232,6 @@ class App {
229232 this . fileInput . addEventListener ( 'change' , ( e ) => {
230233 this . handleFiles ( e . target . files ) ;
231234 } ) ;
232-
233- // Clear button
234- this . clearBtn . addEventListener ( 'click' , ( ) => {
235- this . clearAll ( ) ;
236- } ) ;
237235 }
238236
239237 handleFiles ( files ) {
@@ -259,11 +257,9 @@ class App {
259257 updateFileList ( ) {
260258 if ( this . files . length === 0 ) {
261259 this . fileList . innerHTML = '' ;
262- this . clearBtn . style . display = 'none' ;
263260 return ;
264261 }
265262
266- this . clearBtn . style . display = 'inline-block' ;
267263 this . fileList . innerHTML = '<h3>Uploaded Files:</h3>' ;
268264
269265 this . files . forEach ( ( file , index ) => {
@@ -279,7 +275,13 @@ class App {
279275 this . files . splice ( index , 1 ) ;
280276 this . updateFileList ( ) ;
281277 if ( this . files . length === 0 ) {
282- this . clearAll ( ) ;
278+ this . files = [ ] ;
279+ this . results = [ ] ;
280+ if ( this . fileInput ) {
281+ this . fileInput . value = '' ;
282+ }
283+ this . updateFileList ( ) ;
284+ this . resultsSection . style . display = 'none' ;
283285 } else {
284286 this . processFiles ( ) ;
285287 }
@@ -425,15 +427,35 @@ class App {
425427 }
426428
427429 downloadFile ( result ) {
428- const blob = new Blob ( [ result . cleanedText ] , { type : 'text/plain' } ) ;
429- const url = URL . createObjectURL ( blob ) ;
430- const a = document . createElement ( 'a' ) ;
431- a . href = url ;
432- a . download = result . fileName . replace ( / \. ( t x t | d o c x ) $ / , '_cleaned.txt' ) ;
433- document . body . appendChild ( a ) ;
434- a . click ( ) ;
435- document . body . removeChild ( a ) ;
436- URL . revokeObjectURL ( url ) ;
430+ try {
431+ const blob = new Blob ( [ result . cleanedText ] , { type : 'text/plain;charset=utf-8' } ) ;
432+ const url = URL . createObjectURL ( blob ) ;
433+
434+ // Get original filename and extension
435+ const originalName = result . fileName ;
436+ const nameWithoutExt = originalName . replace ( / \. ( t x t | d o c x ) $ / i, '' ) ;
437+ const downloadName = `${ nameWithoutExt } _cleaned.txt` ;
438+
439+ const a = document . createElement ( 'a' ) ;
440+ a . href = url ;
441+ a . download = downloadName ;
442+ a . style . display = 'none' ;
443+ document . body . appendChild ( a ) ;
444+
445+ // Trigger download
446+ a . click ( ) ;
447+
448+ // Cleanup
449+ setTimeout ( ( ) => {
450+ document . body . removeChild ( a ) ;
451+ URL . revokeObjectURL ( url ) ;
452+ } , 100 ) ;
453+
454+ this . showToast ( `Downloaded: ${ downloadName } ` ) ;
455+ } catch ( error ) {
456+ console . error ( 'Download error:' , error ) ;
457+ this . showToast ( 'Failed to download file' , 'error' ) ;
458+ }
437459 }
438460
439461 copyToClipboard ( text ) {
@@ -458,21 +480,6 @@ class App {
458480 } , 3000 ) ;
459481 }
460482
461- clearAll ( ) {
462- if ( this . files . length === 0 ) {
463- return ;
464- }
465-
466- this . files = [ ] ;
467- this . results = [ ] ;
468- if ( this . fileInput ) {
469- this . fileInput . value = '' ;
470- }
471- this . updateFileList ( ) ;
472- this . resultsSection . style . display = 'none' ;
473- this . showToast ( 'All files cleared' ) ;
474- }
475-
476483 formatFileSize ( bytes ) {
477484 if ( bytes === 0 ) return '0 Bytes' ;
478485 const k = 1024 ;
0 commit comments