본문 바로가기

호그와트

한글 키보드 냠해요 (initial하게 만든 거라 약간 오류 있을 수 있어용)

728x90
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Hangul Keyboard IME</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    #output { border: 1px solid #ccc; padding: 10px; width: 100%; min-height: 150px; }
    #composing { font-size: 1.5em; margin-top: 10px; padding: 5px; border: 1px solid #aaa; min-height: 30px; }
    p { max-width: 600px; }
  </style>
</head>
<body>
  <h1>Hangul Keyboard IME</h1>
  <p>Type on your English keyboard below. The text will be converted into Hangul syllables following the composition rules (initial consonant + medial vowel + optional final consonant).</p>
  <p><strong>Output:</strong></p>
  <div id="output"></div>
  <p><strong>Current Composition:</strong></p>
  <div id="composing"></div>

  <script>
    /***** Data Structures for Hangul Composition *****/
    const initials = ['ㄱ','ㄲ','ㄴ','ㄷ','ㄸ','ㄹ','ㅁ','ㅂ','ㅃ','ㅅ','ㅆ','ㅇ','ㅈ','ㅉ','ㅊ','ㅋ','ㅌ','ㅍ','ㅎ'];
    const medials  = ['ㅏ','ㅐ','ㅑ','ㅒ','ㅓ','ㅔ','ㅕ','ㅖ','ㅗ','ㅘ','ㅙ','ㅚ','ㅛ','ㅜ','ㅝ','ㅞ','ㅟ','ㅠ','ㅡ','ㅢ','ㅣ'];
    const finals   = ['','ㄱ','ㄲ','ㄳ','ㄴ','ㄵ','ㄶ','ㄷ','ㄹ','ㄺ','ㄻ','ㄼ','ㄽ','ㄾ','ㄿ','ㅀ','ㅁ','ㅂ','ㅄ','ㅅ','ㅆ','ㅇ','ㅈ','ㅊ','ㅋ','ㅌ','ㅍ','ㅎ'];

    // Map from English-key (Dubeolsik layout) to Hangul jamo.
    const keyMap = {
      // Consonants
      'r': { type: 'consonant', jamo: 'ㄱ' },
      'R': { type: 'consonant', jamo: 'ㄲ' },
      's': { type: 'consonant', jamo: 'ㄴ' },
      'e': { type: 'consonant', jamo: 'ㄷ' },
      'E': { type: 'consonant', jamo: 'ㄸ' },
      'f': { type: 'consonant', jamo: 'ㄹ' },
      'a': { type: 'consonant', jamo: 'ㅁ' },
      'q': { type: 'consonant', jamo: 'ㅂ' },
      'Q': { type: 'consonant', jamo: 'ㅃ' },
      't': { type: 'consonant', jamo: 'ㅅ' },
      'T': { type: 'consonant', jamo: 'ㅆ' },
      'd': { type: 'consonant', jamo: 'ㅇ' },
      'w': { type: 'consonant', jamo: 'ㅈ' },
      'W': { type: 'consonant', jamo: 'ㅉ' },
      'c': { type: 'consonant', jamo: 'ㅊ' },
      'z': { type: 'consonant', jamo: 'ㅋ' },
      'x': { type: 'consonant', jamo: 'ㅌ' },
      'v': { type: 'consonant', jamo: 'ㅍ' },
      'g': { type: 'consonant', jamo: 'ㅎ' },
      // Vowels
      'k': { type: 'vowel', jamo: 'ㅏ' },
      'o': { type: 'vowel', jamo: 'ㅐ' },
      'i': { type: 'vowel', jamo: 'ㅑ' },
      // (Skipping shift variant for ㅒ)
      'j': { type: 'vowel', jamo: 'ㅓ' },
      'p': { type: 'vowel', jamo: 'ㅔ' },
      'u': { type: 'vowel', jamo: 'ㅕ' },
      'P': { type: 'vowel', jamo: 'ㅖ' },
      'h': { type: 'vowel', jamo: 'ㅗ' },
      'y': { type: 'vowel', jamo: 'ㅛ' },
      'n': { type: 'vowel', jamo: 'ㅜ' },
      'b': { type: 'vowel', jamo: 'ㅠ' },
      'm': { type: 'vowel', jamo: 'ㅡ' },
      'l': { type: 'vowel', jamo: 'ㅣ' }
    };

    // Compound vowels: if a vowel is already present, check if the new vowel can combine.
    const compoundVowels = {
      'ㅗ': { 'ㅏ': 'ㅘ', 'ㅐ': 'ㅙ', 'ㅣ': 'ㅚ' },
      'ㅜ': { 'ㅓ': 'ㅝ', 'ㅔ': 'ㅞ', 'ㅣ': 'ㅟ' },
      'ㅡ': { 'ㅣ': 'ㅢ' }
    };

    // Compound final consonants (for when adding a second consonant after a final)
    const compoundFinals = {
      'ㄱ': { 'ㅅ': 'ㄳ' },
      'ㄴ': { 'ㅈ': 'ㄵ', 'ㅎ': 'ㄶ' },
      'ㄹ': { 'ㄱ': 'ㄺ', 'ㅁ': 'ㄻ', 'ㅂ': 'ㄼ', 'ㅅ': 'ㄽ', 'ㅌ': 'ㄾ', 'ㅍ': 'ㄿ', 'ㅎ': 'ㅀ' },
      'ㅂ': { 'ㅅ': 'ㅄ' }
    };

    // For backspace handling when a compound final is present:
    const decomposeFinal = {
      'ㄳ': ['ㄱ', 'ㅅ'],
      'ㄵ': ['ㄴ', 'ㅈ'],
      'ㄶ': ['ㄴ', 'ㅎ'],
      'ㄺ': ['ㄹ', 'ㄱ'],
      'ㄻ': ['ㄹ', 'ㅁ'],
      'ㄼ': ['ㄹ', 'ㅂ'],
      'ㄽ': ['ㄹ', 'ㅅ'],
      'ㄾ': ['ㄹ', 'ㅌ'],
      'ㄿ': ['ㄹ', 'ㅍ'],
      'ㅀ': ['ㄹ', 'ㅎ'],
      'ㅄ': ['ㅂ', 'ㅅ']
    };

    /***** State Variables *****/
    let currentSyllable = { initial: "", medial: "", final: "" };
    let composedText = "";

    // Display elements
    const outputDiv = document.getElementById("output");
    const composingDiv = document.getElementById("composing");

    function updateDisplay() {
      outputDiv.textContent = composedText;
      composingDiv.textContent = composeSyllable(currentSyllable);
    }

    // Compose a Hangul syllable using the Unicode composition formula.
    function composeSyllable(syllable) {
      if (syllable.initial && syllable.medial) {
        let initIndex = initials.indexOf(syllable.initial);
        let medIndex = medials.indexOf(syllable.medial);
        let finIndex = finals.indexOf(syllable.final);
        if (initIndex === -1 || medIndex === -1 || finIndex === -1) {
          return syllable.initial + syllable.medial + syllable.final;
        }
        return String.fromCharCode(0xAC00 + (initIndex * 588) + (medIndex * 28) + finIndex);
      } else {
        return syllable.initial + syllable.medial + syllable.final;
      }
    }

    // Commit the current syllable and reset.
    function commitSyllable() {
      composedText += composeSyllable(currentSyllable);
      currentSyllable = { initial: "", medial: "", final: "" };
    }

    /***** Key Event Handling *****/
    document.addEventListener("keydown", function(e) {
      // --- Ignore Pure Modifier Keys ---
      if (["Shift", "Control", "Alt", "Meta"].includes(e.key)) {
        return; // Do nothing if the pressed key is just a modifier.
      }

      // --- Backspace Handling ---
      if (e.key === "Backspace") {
        e.preventDefault();
        if (currentSyllable.final) {
          if (currentSyllable.final.length === 2 && decomposeFinal[currentSyllable.final]) {
            currentSyllable.final = decomposeFinal[currentSyllable.final][0];
          } else {
            currentSyllable.final = "";
          }
        } else if (currentSyllable.medial) {
          currentSyllable.medial = "";
        } else if (currentSyllable.initial) {
          currentSyllable.initial = "";
        } else {
          composedText = composedText.slice(0, -1);
        }
        updateDisplay();
        return;
      }

      // --- Space Handling ---
      if (e.key === " ") {
        e.preventDefault();
        commitSyllable();
        composedText += " ";
        updateDisplay();
        return;
      }

      // Look up the mapping for the pressed key.
      let mapping = keyMap[e.key];
      if (!mapping) {
        // If key not mapped, commit current syllable and output the key as-is.
        commitSyllable();
        composedText += e.key;
        updateDisplay();
        return;
      }
      e.preventDefault();

      /***** Process Consonant and Vowel Input *****/
      if (mapping.type === "consonant") {
        if (!currentSyllable.initial) {
          currentSyllable.initial = mapping.jamo;
        }
        else if (currentSyllable.initial && !currentSyllable.medial) {
          currentSyllable.initial = mapping.jamo;
        }
        else if (currentSyllable.initial && currentSyllable.medial) {
          if (!currentSyllable.final) {
            currentSyllable.final = mapping.jamo;
          } else {
            let currFinal = currentSyllable.final;
            if (compoundFinals[currFinal] && compoundFinals[currFinal][mapping.jamo]) {
              currentSyllable.final = compoundFinals[currFinal][mapping.jamo];
            } else {
              commitSyllable();
              currentSyllable.initial = mapping.jamo;
            }
          }
        }
      }
      else if (mapping.type === "vowel") {
        if (!currentSyllable.initial) {
          currentSyllable.initial = "ㅇ";
          currentSyllable.medial = mapping.jamo;
        }
        else if (currentSyllable.initial && !currentSyllable.medial) {
          currentSyllable.medial = mapping.jamo;
        }
        else if (currentSyllable.initial && currentSyllable.medial && !currentSyllable.final) {
          let currMedial = currentSyllable.medial;
          if (compoundVowels[currMedial] && compoundVowels[currMedial][mapping.jamo]) {
            currentSyllable.medial = compoundVowels[currMedial][mapping.jamo];
          } else {
            commitSyllable();
            currentSyllable.initial = "ㅇ";
            currentSyllable.medial = mapping.jamo;
          }
        }
        else if (currentSyllable.initial && currentSyllable.medial && currentSyllable.final) {
          let movedConsonant = currentSyllable.final;
          if (movedConsonant.length === 2 && decomposeFinal[movedConsonant]) {
            let decomposed = decomposeFinal[movedConsonant];
            currentSyllable.final = decomposed[0];
            commitSyllable();
            currentSyllable.initial = decomposed[1];
            currentSyllable.medial = mapping.jamo;
          } else {
            currentSyllable.final = "";
            commitSyllable();
            currentSyllable.initial = movedConsonant;
            currentSyllable.medial = mapping.jamo;
          }
        }
      }
      updateDisplay();
    });
  </script>
</body>
</html>
 
//판도리카 !
728x90

'호그와트' 카테고리의 다른 글

피아노 게임  (0) 2025.02.25
mini go-lf game  (0) 2025.02.07
자~ 골라요 골라  (0) 2025.01.21
수학을 한다는 거  (0) 2024.11.26
crazy attack !!!!!!!!!!!  (0) 2024.11.22