Skip to content

Commit 3cbff2b

Browse files
authored
Add files via upload
1 parent b20d142 commit 3cbff2b

1 file changed

Lines changed: 170 additions & 61 deletions

File tree

3code_mobile.html

Lines changed: 170 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
align-items: center;
4040
background-color: var(--background-color);
4141
min-height: 100vh;
42-
/* 調整 padding-bottom 以容納多一行的數字鍵 */
42+
/* 調整 padding-bottom 以容納鍵盤 */
4343
padding-bottom: 280px;
4444
}
4545

@@ -204,11 +204,26 @@
204204
font-size: 1rem;
205205
font-weight: normal;
206206
}
207+
208+
/* 調整功能鍵的寬度比例 */
209+
.key[data-code="case_shift"],
210+
.key[data-code="lang_toggle"],
211+
.key[data-code="backspace"],
212+
.key[data-code="enter"] {
213+
flex-grow: 1.5;
214+
}
207215

208216
.key.space-key {
209-
flex: 2;
217+
flex: 3.5; /* 讓空白鍵更寬 */
210218
background-color: #c5cae9;
211219
}
220+
221+
/* 調整 A-Row 和 Z-Row 的鍵寬,使其能夠容納更多或更少的鍵 */
222+
.key-row:nth-child(3) .key, /* A-Row, 12 keys */
223+
.key-row:nth-child(4) .key { /* Z-Row, 10 keys */
224+
flex-grow: 1;
225+
flex-basis: auto;
226+
}
212227

213228
/* 按鍵互動效果 */
214229
.key:active {
@@ -237,35 +252,103 @@
237252
</div>
238253

239254
<script>
240-
// --- 資料處理與解析 ---
255+
// --- 狀態變數 ---
241256
let currentCodemap = {};
242257
let currentReverseCodemap = {};
258+
let isEnglishMode = false;
259+
let isShiftActive = false; // 控制大寫和符號切換的狀態
243260

244-
// 中文模式下的鍵盤顯示 (Shift 鍵顯示為 '三碼')
245-
const keyname_map_upper = {
246-
'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D', 'e': 'E', 'f': 'F', 'g': 'G',
247-
'h': 'H', 'i': 'I', 'j': 'J', 'k': 'K', 'l': 'L', 'm': 'M', 'n': 'N',
248-
'o': 'O', 'p': 'P', 'q': 'Q', 'r': 'R', 's': 'S', 't': 'T', 'u': 'U',
249-
'v': 'V', 'w': 'W', 'x': 'X', 'y': 'Y', 'z': 'Z',
250-
// 數字與符號對應 (按鍵顯示)
251-
'1': '1', '2': '2', '3': '3', '4': '4', '5': '5',
252-
'6': '6', '7': '7', '8': '8', '9': '9', '0': '0',
253-
"'": "〃", ';': ';', ',': ',', '.': '.', '/': '/', ' ': '空白鍵', 'enter': 'Enter', 'backspace': '刪除鍵',
254-
'shift': '三碼',
261+
// --- 鍵盤顯示內容映射表 (四種狀態) ---
262+
263+
// 字母鍵的基礎映射
264+
const letter_maps = {
265+
'cn_normal': (key) => key.toUpperCase(), // 中文模式顯示大寫字母 (A-Z)
266+
// 中文模式下,字母鍵的顯示不隨 Shift 改變,維持大寫
267+
'cn_shifted': (key) => key.toUpperCase(),
268+
'en_normal': (key) => key.toLowerCase(), // 英文模式顯示小寫字母 (a-z)
269+
'en_shifted': (key) => key.toUpperCase() // 英文 Shift 模式顯示大寫字母 (A-Z)
255270
};
256-
// 英文模式下的鍵盤顯示 (Shift 鍵顯示為 'En')
257-
const keyname_map_lower = {
258-
'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd', 'e': 'e', 'f': 'f', 'g': 'g',
259-
'h': 'h', 'i': 'i', 'j': 'j', 'k': 'k', 'l': 'l', 'm': 'm', 'n': 'n',
260-
'o': 'o', 'p': 'p', 'q': 'q', 'r': 'r', 's': 's', 't': 't', 'u': 'u',
261-
'v': 'v', 'w': 'w', 'x': 'x', 'y': 'y', 'z': 'z',
262-
// 數字與符號對應
263-
'1': '1', '2': '2', '3': '3', '4': '4', '5': '5',
264-
'6': '6', '7': '7', '8': '8', '9': '9', '0': '0',
265-
"'": "'", ';': ';', ',': ',', '.': '.', '/': '/', ' ': ' ', 'enter': 'Enter', 'backspace': '刪除鍵',
266-
'shift': 'En',
271+
272+
const key_display_maps = {
273+
// [0, 0] Chinese Normal (Default)
274+
'cn_normal': {
275+
// Numbers/Symbols: 中文輸入法的預設符號 (數字輸出,符號編碼)
276+
'1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', '0': '0',
277+
';': ';', "'": '〃', ',': ',', '.': '.', '/': '/',
278+
'lang_toggle': '三碼', // 顯示 '三碼' (當前模式)
279+
'case_shift': '⇧',
280+
'backspace': '⌫', // 顯示 '⌫'
281+
'enter': '↵', // 顯示 '↵'
282+
' ': ' ' // 修正: 顯示 ' ' (單一空白字元)
283+
},
284+
// [0, 1] Chinese Shifted (與 cn_normal 相同,除了 case_shift 鍵本身)
285+
'cn_shifted': {
286+
'1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', '0': '0',
287+
';': ';', "'": '〃', ',': ',', '.': '.', '/': '/',
288+
'lang_toggle': '三碼',
289+
'case_shift': '⬆', // 只有 Shift 鍵的視覺改變
290+
'backspace': '⌫',
291+
'enter': '↵',
292+
' ': ' '
293+
},
294+
// [1, 0] English Normal (Lowercase)
295+
'en_normal': {
296+
'1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', '0': '0',
297+
// 英文模式預設符號
298+
';': ';', "'": "'", ',': ',', '.': '.', '/': '/',
299+
'lang_toggle': 'En', // 顯示 'En' (當前模式)
300+
'case_shift': '⇧',
301+
'backspace': '⌫',
302+
'enter': '↵',
303+
' ': ' '
304+
},
305+
// [1, 1] English Shifted (Uppercase + Secondary Symbols)
306+
'en_shifted': {
307+
// Shifted Symbols (直接輸出)
308+
'1': '!', '2': '@', '3': '#', '4': '$', '5': '%', '6': '^', '7': '&', '8': '*', '9': '(', '0': ')',
309+
// 英文上檔符號
310+
';': ':', "'": '"', ',': '<', '.': '>', '/': '?',
311+
'lang_toggle': 'En',
312+
'case_shift': '⬆',
313+
'backspace': '⌫',
314+
'enter': '↵',
315+
' ': ' '
316+
}
267317
};
268318

319+
// --- 輔助函數:取得實際輸出字元 ---
320+
321+
function getCurrentDisplayMap() {
322+
let mode = isEnglishMode ? 'en' : 'cn';
323+
let shift = isShiftActive ? 'shifted' : 'normal';
324+
return key_display_maps[`${mode}_${shift}`];
325+
}
326+
327+
// 獲取當前模式下按下某個鍵時應輸出的實際字元(非編碼鍵)
328+
function getOutputChar(code) {
329+
const mapKey = isEnglishMode ? (isShiftActive ? 'en_shifted' : 'en_normal') :
330+
(isShiftActive ? 'cn_shifted' : 'cn_normal');
331+
const map = key_display_maps[mapKey];
332+
333+
// 1. 檢查是否為英文模式下的直接輸出 (字母, 數字, 符號)
334+
if (isEnglishMode) {
335+
if (code.match(/^[a-z]$/)) {
336+
// 英文模式下,字母直接輸出大小寫
337+
return letter_maps[mapKey](code);
338+
}
339+
if (code.match(/^[0-9;'./,<> ]$/)) { // 包含 space
340+
// 英文模式下,數字和符號直接輸出半形/上檔符號
341+
return map[code] || code; // map[code] 對於數字和符號會輸出正確的上檔符號或數字,對於 ' ' 則輸出 ' '
342+
}
343+
return null;
344+
}
345+
346+
// 2. 檢查是否為中文模式下的直接輸出 (無,中文模式下的數字輸出在 handleChineseInput 中處理)
347+
return null;
348+
}
349+
350+
// --- 舊有代碼區塊 ---
351+
269352
// DOM 元素
270353
const textOutput = document.getElementById('text-output');
271354
const mainInput = document.getElementById('main-input');
@@ -277,8 +360,7 @@
277360
const MAX_CODE_LENGTH = 3;
278361
let currentCode = '';
279362
let currentCandidates = [];
280-
let isEnglishMode = false;
281-
363+
282364
function parseCinData(data) {
283365
const newCodemap = {};
284366
const newReverseCodemap = {};
@@ -305,6 +387,7 @@
305387
}
306388

307389
async function loadSecondaryCodemap() {
390+
// 注意:這裡假設您的編碼檔名為 3codes2.txt 並且在同目錄
308391
const fileName = './3codes2.txt';
309392
try {
310393
const response = await fetch(fileName);
@@ -332,10 +415,12 @@
332415
if (currentCandidates.length > 0) {
333416
selectCandidate(0); // 如果有編碼,先上字
334417
}
335-
textOutput.textContent += inputChar; // 直接輸出數字
418+
// 中文模式的數字直接輸出數字
419+
textOutput.textContent += inputChar;
336420
return;
337421
}
338422

423+
// 2. 處理功能鍵 (與 Shift 狀態無關)
339424
if (code === 'backspace') {
340425
if (currentCode.length > 0) {
341426
currentCode = currentCode.slice(0, -1);
@@ -358,12 +443,12 @@
358443
if (currentCandidates.length > 0) {
359444
selectCandidate(0);
360445
} else {
361-
textOutput.textContent += ' ';
446+
textOutput.textContent += ' '; // 輸出全形空白
362447
}
363448
return;
364449
}
365450

366-
// 2. 字母 (a-z) 和符號 (;'./,) 用於編碼
451+
// 3. 字母 (a-z) 和編碼符號 (;'./,) 用於編碼
367452
if (inputChar.match(/^[a-z;'./,<>]$/)) {
368453
if (currentCode.length === MAX_CODE_LENGTH) {
369454
if (currentCandidates.length > 0) {
@@ -378,32 +463,33 @@
378463
}
379464

380465
// --- 處理英文模式輸入 ---
381-
function handleEnglishInput(char) {
382-
// 處理功能鍵
383-
if (char === 'backspace') {
466+
function handleEnglishInput(code) {
467+
// 1. 處理功能鍵
468+
if (code === 'backspace') {
384469
if (textOutput.textContent.length > 0) {
385470
textOutput.textContent = textOutput.textContent.slice(0, -1);
386471
}
387472
return;
388473
}
389-
if (char === 'enter') {
474+
if (code === 'enter') {
390475
textOutput.textContent += '\n';
391476
return;
392477
}
393-
if (char === ' ') {
394-
textOutput.textContent += ' ';
478+
if (code === ' ') {
479+
textOutput.textContent += ' '; // 輸出半形空白
395480
return;
396481
}
397-
398-
// 處理英文字母、數字和符號
399-
if (char.length === 1) {
400-
textOutput.textContent += char;
482+
483+
// 2. 處理英文字母、數字和符號
484+
const outputChar = getOutputChar(code);
485+
if (outputChar) {
486+
textOutput.textContent += outputChar;
401487
}
402488
}
403489

404490
// --- 核心狀態更新與顯示函數 (中文模式專用) ---
405491
function updateStateAndDisplay() {
406-
mainInput.textContent = formatCode(currentCode);
492+
mainInput.textContent = formatCode(currentCode);
407493
currentCandidates = currentCodemap[currentCode] || [];
408494

409495
if (currentCode.length === MAX_CODE_LENGTH) {
@@ -455,43 +541,49 @@
455541
function resetInputState() {
456542
currentCode = '';
457543
currentCandidates = [];
544+
545+
// 更新輸入提示文字
458546
mainInput.textContent = isEnglishMode ? '英文模式' : '編碼顯示在此';
459547
showCandidates();
460548
}
461549

462550
// --- 格式化編碼顯示 ---
463551
function formatCode(code) {
464552
let displayString = '';
553+
const map = key_display_maps.cn_normal;
465554
for (const char of code) {
466-
displayString += keyname_map_upper[char] || char.toUpperCase();
555+
displayString += (char.match(/^[a-z]$/) ? char.toUpperCase() : map[char]) || char.toUpperCase();
467556
}
468557
return displayString;
469558
}
470559

471560
// --- 更新鍵盤按鍵顯示 ---
472561
function updateKeyboardDisplay() {
473-
const map = isEnglishMode ? keyname_map_lower : keyname_map_upper;
562+
const map = getCurrentDisplayMap();
563+
// 中文模式下,字母鍵的視覺始終是 letter_maps.cn_normal (大寫 A-Z)
564+
const letterMap = isEnglishMode ? (isShiftActive ? letter_maps.en_shifted : letter_maps.en_normal) : letter_maps.cn_normal;
565+
474566
document.querySelectorAll('.key[data-code]').forEach(keyElement => {
475567
const code = keyElement.dataset.code;
568+
476569
if (map[code]) {
570+
// 處理非字母鍵和特殊功能鍵 (包括 ' ')
477571
keyElement.textContent = map[code];
572+
} else if (code.match(/^[a-z]$/)) {
573+
// 處理字母鍵 (a-z)
574+
keyElement.textContent = letterMap(code);
478575
}
479576
});
480-
481-
const shiftKey = document.querySelector('.key[data-code="shift"]');
482-
if (shiftKey) {
483-
shiftKey.textContent = isEnglishMode ? keyname_map_lower['shift'] : keyname_map_upper['shift'];
484-
}
485577
}
486578

487-
// --- 動態生成手機優化鍵盤 (新增數字行) ---
579+
// --- 動態生成手機優化鍵盤 (符號鍵位置修正) ---
488580
function generateMobileKeyboard() {
489581
const layout_mobile = [
490-
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], // 新增數字行
582+
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
491583
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
492-
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';'],
493-
['Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/', "'"],
494-
['Shift', 'Space', 'Back', 'Enter']
584+
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', "'"],
585+
['Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/'],
586+
['Case_Shift', 'Lang_Toggle', 'Space', 'Back', 'Enter']
495587
];
496588

497589
keyboardContainer.innerHTML = '';
@@ -506,7 +598,7 @@
506598

507599
let code = keyText.toLowerCase();
508600

509-
// 設定 data-code
601+
// 設定 data-code 和樣式
510602
if (keyText === 'Back') {
511603
code = 'backspace';
512604
key.classList.add('function-key');
@@ -516,19 +608,36 @@
516608
} else if (keyText === 'Space') {
517609
code = ' ';
518610
key.classList.add('space-key');
519-
} else if (keyText === 'Shift') {
520-
code = 'shift';
611+
} else if (keyText === 'Lang_Toggle') {
612+
code = 'lang_toggle';
613+
key.classList.add('function-key');
614+
} else if (keyText === 'Case_Shift') {
615+
code = 'case_shift';
521616
key.classList.add('function-key');
522617
}
523618

524619
key.dataset.code = code;
525-
key.textContent = keyname_map_upper[code] || keyText;
620+
621+
// 初始顯示: 根據初始模式 (中文, normal) 顯示正確的圖示或文字
622+
const initialMap = getCurrentDisplayMap();
623+
if (initialMap[code]) {
624+
key.textContent = initialMap[code];
625+
} else if (code.match(/^[a-z]$/)) {
626+
key.textContent = letter_maps.cn_normal(code);
627+
} else {
628+
key.textContent = keyText; // 保險措施
629+
}
526630

631+
// --- 鍵盤點擊事件 ---
527632
key.addEventListener('click', () => {
528-
if (code === 'shift') {
633+
if (code === 'lang_toggle') {
529634
isEnglishMode = !isEnglishMode;
635+
isShiftActive = false;
636+
updateKeyboardDisplay();
637+
resetInputState(); // 模式切換後重設輸入狀態並更新提示文字
638+
} else if (code === 'case_shift') {
639+
isShiftActive = !isShiftActive;
530640
updateKeyboardDisplay();
531-
resetInputState();
532641
} else if (isEnglishMode) {
533642
handleEnglishInput(code);
534643
} else {
@@ -544,7 +653,7 @@
544653
}
545654

546655
/**
547-
* 新增功能:複製文字
656+
* 複製文字
548657
*/
549658
function copyTextToClipboard() {
550659
const textToCopy = textOutput.textContent;
@@ -576,7 +685,7 @@
576685
}
577686

578687
/**
579-
* 新增功能:清空文字
688+
* 清空文字
580689
*/
581690
function clearOutput() {
582691
if (confirm('確定要清空所有已輸入的文字嗎?')) {

0 commit comments

Comments
 (0)