@@ -400,25 +400,24 @@ <h2>輸入法模式:</h2>
400400 </ div >
401401 </ div >
402402 < script >
403- // --- 資料處理與解析 ---
403+ // --- 核心變數與元素 ---
404+ let currentCode = '' ;
405+ let currentCandidates = [ ] ;
404406 let primaryCodemap = { } ;
405407 let secondaryCodemap = { } ;
406408 let currentCodemap = { } ;
407409 let currentReverseCodemap = { } ;
408- let currentCode = '' ;
409- let currentCandidates = [ ] ;
410410 let isEnglishMode = false ;
411- let shiftTimer = null ;
412- const textOutput = document . getElementById ( 'text-output' ) ;
411+
412+ const output = document . getElementById ( 'text-output' ) ;
413413 const mainInput = document . getElementById ( 'main-input' ) ;
414- const candidateDisplay = document . getElementById ( 'candidate-display' ) ;
414+ const candidateArea = document . getElementById ( 'candidate-display' ) ;
415+ const keyboard = document . querySelector ( '.keyboard-container' ) ;
415416 const searchInput = document . getElementById ( 'search-input' ) ;
416417 const searchResult = document . getElementById ( 'search-result' ) ;
417418 const modeDisplay = document . getElementById ( 'mode-display' ) ;
418- const modeSwitcher = document . querySelector ( '.mode-switcher' ) ;
419- const keyboardContainer = document . querySelector ( '.keyboard-container' ) ;
420419
421- // --- 載入碼表檔案 ---
420+ // --- 載入碼表檔案(已修復) ---
422421 async function loadCodemap ( filePath ) {
423422 try {
424423 const response = await fetch ( filePath ) ;
@@ -433,14 +432,14 @@ <h2>輸入法模式:</h2>
433432 return { forward : { } , reverse : { } } ;
434433 }
435434 }
436-
437- // --- 解析 Cin 格式檔案內容 ---
435+
436+ // --- 解析 Cin 格式檔案內容(已修復) ---
438437 function parseCinLikeFile ( text ) {
439438 const lines = text . split ( '\n' ) ;
440439 const codemap = { } ;
441440 const reverseCodemap = { } ;
442441 let inDataSection = false ;
443-
442+
444443 for ( const line of lines ) {
445444 const trimmedLine = line . trim ( ) ;
446445 if ( trimmedLine . startsWith ( '[data]' ) ) {
@@ -457,12 +456,11 @@ <h2>輸入法模式:</h2>
457456 codemap [ code ] = [ ] ;
458457 }
459458 codemap [ code ] . push ( ...chars . split ( '' ) ) ;
460-
459+
461460 chars . split ( '' ) . forEach ( char => {
462461 if ( ! reverseCodemap [ char ] ) {
463462 reverseCodemap [ char ] = [ ] ;
464463 }
465- // 避免重複編碼
466464 if ( ! reverseCodemap [ char ] . includes ( code ) ) {
467465 reverseCodemap [ char ] . push ( code ) ;
468466 }
@@ -478,15 +476,15 @@ <h2>輸入法模式:</h2>
478476
479477 // --- 輸入法核心邏輯 ---
480478 function updateCandidates ( ) {
481- candidateDisplay . innerHTML = '' ;
479+ candidateArea . innerHTML = '' ;
482480 currentCandidates = currentCodemap [ currentCode ] || [ ] ;
483-
481+
484482 if ( currentCode . length > 0 ) {
485483 const codeSpan = document . createElement ( 'span' ) ;
486484 codeSpan . textContent = `[${ currentCode } ]` ;
487485 codeSpan . style . color = '#7986cb' ;
488486 codeSpan . style . fontWeight = 'bold' ;
489- candidateDisplay . appendChild ( codeSpan ) ;
487+ candidateArea . appendChild ( codeSpan ) ;
490488 }
491489
492490 if ( currentCandidates . length > 0 ) {
@@ -495,13 +493,13 @@ <h2>輸入法模式:</h2>
495493 candidateSpan . textContent = `${ index + 1 } . ${ char } ` ;
496494 candidateSpan . dataset . char = char ;
497495 candidateSpan . dataset . index = index ;
498- candidateDisplay . appendChild ( candidateSpan ) ;
496+ candidateArea . appendChild ( candidateSpan ) ;
499497 } ) ;
500498 } else if ( currentCode . length > 0 ) {
501499 const noCandidatesSpan = document . createElement ( 'span' ) ;
502500 noCandidatesSpan . textContent = '找不到字' ;
503501 noCandidatesSpan . style . color = 'red' ;
504- candidateDisplay . appendChild ( noCandidatesSpan ) ;
502+ candidateArea . appendChild ( noCandidatesSpan ) ;
505503 }
506504 }
507505
@@ -511,24 +509,22 @@ <h2>輸入法模式:</h2>
511509 updateCandidates ( ) ;
512510 }
513511
514- // --- 鍵盤與模式切換 ---
515- function switchInputMethod ( mode ) {
516- if ( mode === 'primary' ) {
512+ // --- 模式與鍵盤處理 ---
513+ function switchInputMethod ( method ) {
514+ if ( method === 'primary' ) {
517515 currentCodemap = primaryCodemap . forward ;
518516 currentReverseCodemap = primaryCodemap . reverse ;
519- modeDisplay . textContent = '模式:三碼' ;
520517 } else {
521518 currentCodemap = secondaryCodemap . forward ;
522519 currentReverseCodemap = secondaryCodemap . reverse ;
523- modeDisplay . textContent = '模式:三碼次常' ;
524520 }
525521 resetInputState ( ) ;
526- const radioButtons = modeSwitcher . querySelectorAll ( 'input[type="radio"]' ) ;
527- radioButtons . forEach ( radio => {
528- if ( radio . value === mode ) {
529- radio . checked = true ;
530- }
531- } ) ;
522+ updateModeDisplay ( ) ;
523+ }
524+
525+ function updateModeDisplay ( ) {
526+ const modeName = document . querySelector ( 'input[name="input_mode"]:checked' ) . nextElementSibling . textContent ;
527+ modeDisplay . textContent = `模式: ${ isEnglishMode ? '英數' : modeName } ` ;
532528 }
533529
534530 // --- 事件處理 ---
@@ -541,165 +537,126 @@ <h2>輸入法模式:</h2>
541537 updateCandidates ( ) ;
542538 } ) ;
543539
544- // 監聽鍵盤點擊事件
545- keyboardContainer . addEventListener ( 'click' , ( event ) => {
546- const keyDiv = event . target . closest ( '.key' ) ;
547- if ( ! keyDiv ) return ;
548-
549- const code = keyDiv . dataset . code ;
550- handleKey ( code ) ;
551- } ) ;
552-
553- // 監聽候選字點擊事件
554- candidateDisplay . addEventListener ( 'click' , ( event ) => {
555- const candidateSpan = event . target . closest ( 'span' ) ;
556- if ( candidateSpan && candidateSpan . dataset . char ) {
557- textOutput . textContent += candidateSpan . dataset . char ;
558- resetInputState ( ) ;
559- }
560- } ) ;
561-
562- // 監聽模式切換
563- modeSwitcher . addEventListener ( 'change' , ( event ) => {
540+ document . querySelector ( '.mode-switcher' ) . addEventListener ( 'change' , ( event ) => {
564541 if ( event . target . name === 'input_mode' ) {
565542 switchInputMethod ( event . target . value ) ;
566543 }
567544 } ) ;
568-
569- // 監聽反向查詢輸入
570- searchInput . addEventListener ( 'input' , ( ) => {
571- const charToSearch = searchInput . value . trim ( ) ;
572- searchResult . textContent = '查詢結果顯示在此' ;
573- if ( charToSearch . length === 1 ) {
574- const codes = currentReverseCodemap [ charToSearch ] || [ ] ;
575- if ( codes . length > 0 ) {
576- searchResult . textContent = `編碼:${ codes . join ( '、' ) } ` ;
577- } else {
578- searchResult . textContent = '找不到該漢字編碼。' ;
579- }
545+
546+ candidateArea . addEventListener ( 'click' , ( event ) => {
547+ const candidate = event . target . closest ( 'span[data-char]' ) ;
548+ if ( candidate ) {
549+ const char = candidate . dataset . char ;
550+ output . textContent += char ;
551+ resetInputState ( ) ;
580552 }
581553 } ) ;
582554
583- // 處理鍵盤輸入事件
584- function handleKey ( key ) {
585- if ( isEnglishMode ) {
586- if ( key === 'backspace' ) {
587- textOutput . textContent = textOutput . textContent . slice ( 0 , - 1 ) ;
588- } else if ( key === 'enter' ) {
589- textOutput . textContent += '\n' ;
590- } else if ( key === 'shift' ) {
591- isEnglishMode = false ;
592- modeDisplay . textContent = '模式:三碼' ;
593- } else {
594- textOutput . textContent += key ;
595- }
596- return ;
597- }
598-
599- // 中文模式
600- const validKeys = "abcdefghijklmnopqrstuvwxyz;,." ;
601- if ( validKeys . includes ( key ) && currentCode . length < 3 ) {
602- currentCode += key ;
603- mainInput . value = currentCode ;
604- updateCandidates ( ) ;
605- } else if ( key === 'backspace' ) {
606- if ( currentCode . length > 0 ) {
607- currentCode = currentCode . slice ( 0 , - 1 ) ;
608- mainInput . value = currentCode ;
609- updateCandidates ( ) ;
610- } else {
611- textOutput . textContent = textOutput . textContent . slice ( 0 , - 1 ) ;
612- }
613- } else if ( key === ' ' ) {
614- if ( currentCandidates . length > 0 ) {
615- textOutput . textContent += currentCandidates [ 0 ] ;
616- resetInputState ( ) ;
617- } else {
618- textOutput . textContent += ' ' ;
619- }
620- } else if ( ! isNaN ( parseInt ( key , 10 ) ) ) {
621- const index = parseInt ( key , 10 ) - 1 ;
622- if ( index >= 0 && index < currentCandidates . length ) {
623- textOutput . textContent += currentCandidates [ index ] ;
624- resetInputState ( ) ;
625- }
626- } else if ( key === 'shift' ) {
627- isEnglishMode = true ;
628- modeDisplay . textContent = '模式:英數' ;
629- resetInputState ( ) ;
630- } else if ( key === 'enter' ) {
631- textOutput . textContent += '\n' ;
632- resetInputState ( ) ;
633- } else {
634- textOutput . textContent += key ;
635- }
636- }
555+ // 監聽鍵盤點擊事件
556+ keyboard . addEventListener ( 'click' , ( event ) => {
557+ const keyDiv = event . target . closest ( '.key' ) ;
558+ if ( ! keyDiv ) return ;
559+ const key = keyDiv . dataset . code ;
560+ handleKey ( key ) ;
561+ } ) ;
637562
638- // 監聽實體鍵盤
563+ // 監聽實體鍵盤事件
639564 document . addEventListener ( 'keydown' , ( event ) => {
640565 const key = event . key . toLowerCase ( ) ;
641566 const keyMap = {
642567 'backspace' : 'backspace' ,
643568 'enter' : 'enter' ,
644569 ' ' : ' ' ,
645570 'shift' : 'shift' ,
646- '~' : '`' ,
647- '!' : '1' ,
648- '@' : '2' ,
649- '#' : '3' ,
650- '$' : '4' ,
651- '%' : '5' ,
652- '^' : '6' ,
653- '&' : '7' ,
654- '*' : '8' ,
655- '(' : '9' ,
656- ')' : '0' ,
657- '-' : '-' ,
658- '=' : '=' ,
659- '[' : '[' ,
660- ']' : ']' ,
661- '\\' : '\\' ,
662- ';' : ';' ,
663- "'" : "'" ,
664- ',' : ',' ,
665- '.' : '.' ,
666- '/' : '/' ,
571+ '~' : '~' ,
572+ '!' : '1' , '@' : '2' , '#' : '3' , '$' : '4' , '%' : '5' , '^' : '6' , '&' : '7' , '*' : '8' , '(' : '9' , ')' : '0' ,
573+ '-' : '-' , '=' : '=' , '[' : '[' , ']' : ']' , '\\' : '\\' , ';' : ';' , "'" : "'" , ',' : ',' , '.' : '.' , '/' : '/' ,
667574 'q' : 'q' , 'w' : 'w' , 'e' : 'e' , 'r' : 'r' , 't' : 't' , 'y' : 'y' , 'u' : 'u' , 'i' : 'i' , 'o' : 'o' , 'p' : 'p' ,
668575 'a' : 'a' , 's' : 's' , 'd' : 'd' , 'f' : 'f' , 'g' : 'g' , 'h' : 'h' , 'j' : 'j' , 'k' : 'k' , 'l' : 'l' ,
669576 'z' : 'z' , 'x' : 'x' , 'c' : 'c' , 'v' : 'v' , 'b' : 'b' , 'n' : 'n' , 'm' : 'm'
670577 } ;
671578
579+ const inputKey = keyMap [ key ] || key ;
580+
581+ // 處理 Shift 鍵切換模式
672582 if ( event . key === "Shift" ) {
673- if ( event . repeat ) return ;
583+ if ( event . repeat ) return ; // 避免長按時重複觸發
674584 isEnglishMode = ! isEnglishMode ;
675- modeDisplay . textContent = isEnglishMode ? '模式:英數' : '模式:三碼' ;
585+ updateModeDisplay ( ) ;
676586 resetInputState ( ) ;
587+ event . preventDefault ( ) ; // 阻止瀏覽器默認行為
677588 return ;
678589 }
679590
680591 // 在英數模式下處理所有輸入
681592 if ( isEnglishMode ) {
682- if ( event . key . length === 1 || event . key === 'Backspace' || event . key === 'Enter' ) {
683- textOutput . textContent += event . key ;
593+ if ( event . key . length === 1 ) {
594+ output . textContent += event . key ;
595+ } else if ( event . key === 'Backspace' ) {
596+ output . textContent = output . textContent . slice ( 0 , - 1 ) ;
597+ } else if ( event . key === 'Enter' ) {
598+ output . textContent += '\n' ;
684599 }
685600 return ;
686601 }
687602
688603 // 在中文模式下處理
689- const inputKey = keyMap [ key ] ;
690604 if ( inputKey ) {
691605 event . preventDefault ( ) ; // 阻止瀏覽器默認行為
692606 handleKey ( inputKey ) ;
693607 } else if ( event . key >= '1' && event . key <= '9' ) {
694608 const index = parseInt ( event . key , 10 ) - 1 ;
695609 if ( index < currentCandidates . length ) {
696- textOutput . textContent += currentCandidates [ index ] ;
610+ output . textContent += currentCandidates [ index ] ;
697611 resetInputState ( ) ;
698612 }
699613 } else if ( event . key . length === 1 ) { // 處理未映射的單個字元
700- textOutput . textContent += event . key ;
614+ output . textContent += event . key ;
701615 }
702616 } ) ;
703- </ script >
704617
618+ // 處理鍵盤與物理鍵盤的共用邏輯
619+ function handleKey ( key ) {
620+ const validCodeKeys = "1234567890abcdefghijklmnopqrstuvwxyz;',./" ;
621+
622+ if ( validCodeKeys . includes ( key ) && currentCode . length < 3 ) {
623+ currentCode += key ;
624+ mainInput . value = currentCode ;
625+ updateCandidates ( ) ;
626+ } else if ( key === 'backspace' ) {
627+ if ( currentCode . length > 0 ) {
628+ currentCode = currentCode . slice ( 0 , - 1 ) ;
629+ mainInput . value = currentCode ;
630+ updateCandidates ( ) ;
631+ } else {
632+ output . textContent = output . textContent . slice ( 0 , - 1 ) ;
633+ }
634+ } else if ( key === ' ' ) {
635+ if ( currentCandidates . length > 0 ) {
636+ output . textContent += currentCandidates [ 0 ] ;
637+ resetInputState ( ) ;
638+ } else {
639+ output . textContent += ' ' ;
640+ }
641+ } else if ( key === 'enter' ) {
642+ output . textContent += '\n' ;
643+ resetInputState ( ) ;
644+ }
645+ }
646+
647+ // --- 反向查詢事件處理 ---
648+ searchInput . addEventListener ( 'input' , ( ) => {
649+ const charToSearch = searchInput . value . trim ( ) ;
650+ searchResult . textContent = '查詢結果顯示在此' ;
651+ if ( charToSearch . length === 1 ) {
652+ const codes = currentReverseCodemap [ charToSearch ] || [ ] ;
653+ if ( codes . length > 0 ) {
654+ searchResult . textContent = `編碼:${ codes . join ( '、' ) } ` ;
655+ } else {
656+ searchResult . textContent = '找不到該漢字編碼。' ;
657+ }
658+ }
659+ } ) ;
660+
661+ </ script >
705662</ body > </ html >
0 commit comments