jack
jack

Reputation: 315

Javascript - a problem with a two-step text input word conversion

Here I am making a word conversion tool which changes a certain word X into Y, or X to Y to Z by using javascript.

Progress: HERE

Here is the entire javascript:

var conversion = {
"one":"two",
};
var conversion2 = {
"two":"three",
};

 var maxLength = Object.keys(conversion)
    .reduce((a, b) => a.length > b.length ? a : b) 
    .length;

  function convert (text) {
    var converted = "";
    var cur = 0;
    while (cur < text.length) {
      var testedPhoneme;
      var symbol = undefined;
      for (var length = maxLength; length > 0; length --) {
        testedPhoneme = text.substr(cur, length);
        if (conversion[testedPhoneme]) {
          symbol = conversion[testedPhoneme];
          break; // stop the loop
        }
      }
      if (symbol) {
        converted += symbol;
        cur += testedPhoneme.length;
      }
      else {
        converted += text[cur]
        cur++;
      }
    }
    return converted
  }


 var maxLength2 = Object.keys(conversion2)
    .reduce((a, b) => a.length > b.length ? a : b) 
    .length; 
  
  function convert2 (text) {
    var converted2 = "";
    var cur2 = 0;
    while (cur2 < text.length) {
      var testedPhoneme2;
      var symbol2 = undefined;
      for (var length = maxLength2; length > 0; length --) {
        testedPhoneme2 = text.substr(cur2, length);
        if (conversion2[testedPhoneme2]) {
          symbol2 = conversion2[testedPhoneme2];
          break; // stop the loop
        }
      }
      if (symbol2) {
        converted2 += symbol2;
        cur2 += testedPhoneme2.length;
      }
      else {
        converted2 += text[cur2]
        cur2++;
      }
    }
    return converted2
  }

  function onInputTextChange(txt) {
    var outputTextareaElem = document.getElementById("output_textarea");
    var div = document.createElement("div");
    var outputHtmlEntities = convert(txt);
    div.innerHTML = outputHtmlEntities;
    outputTextareaElem.value = div.innerText;
  }

  function onOutputTextChange(txt) {
    var outputTextareaElem2 = document.getElementById("output_textarea2");
    var div = document.createElement("div");
    var outputHtmlEntities2 = convert2(txt);
    div.innerHTML = outputHtmlEntities2;
    outputTextareaElem2.value = div.innerText;
  }

In the page that I made so far, there are three <textarea>s; Input, Output and Output2.

Currently, thanks to this piece of code;

var conversion = {
"one":"two",
};
var conversion2 = {
"two":"three",
};

If one is typed into Input, Output renders two. If two is manually typed into Output, three gets rendered in Output2.

Here is the problem, I want to render three in Output2 only through typing one into Input, but a direct two-step conversion seems unavailable yet. In other words, Input > Output (one > two) and Output > Output2 (two > three) conversion is available, but Input > Output > Output2 (one > two > three) is unavailable.

What needs to be done to solve this? Any help would be appreciated.

Upvotes: 0

Views: 83

Answers (2)

gui3
gui3

Reputation: 1867

Ok, not exactly what you asked, but I could do something that works

Here is the example : https://jsfiddle.net/alias_gui3/8knw57u0/94/

how to use it :

to add new characters OR new languages/scripts

just complete the dictionnary :

var dictionnary = [
  {
    latin: "u",
    japanese: "う",
    emoji: "👋"
    // add any script for every characters
  },{
    latin: "ku",
    japanese: "く",
    emoji: "👀"
  },{
    latin: "tsu",
    japanese: "つ",
    emoji: "🤖"
  }
  // add any character with the same format
]

to add new textareas :

give your textarea a recognizable id (eg. id="cyrillic") then connect your textarea with this method:

// connect your textareas below !!
addTextArea(
  document.querySelector("#latin"), 
  "latin"
);
addTextArea(
  document.querySelector("#japanese"), 
  "japanese"
);
addTextArea(
  document.querySelector("#emoji"), 
  "emoji"
);
// add new textarea with a new language here

then all the connections are done, you can edit all your textareas, if they recognise a character they will translate it in all the other textareas


full code

var dictionnary = [
  {
    latin: "u",
    japanese: "う",
    emoji: "👋"
    // add any script for every characters
  },{
    latin: "ku",
    japanese: "く",
    emoji: "👀"
  },{
    latin: "tsu",
    japanese: "つ",
    emoji: "🤖"
  }
  // add any character with the same format
]
// calculate the max length for each language :
var max = {}
dictionnary.forEach(
  char => {
    Object.keys(char).forEach(script => {
      max[script] = max[script]
        ? char[script].length > max[script]
          ? char[script].length
          : max[script]
        : char[script].length
    })
  }
)// now max contains the maximum length of sequence
// for each language

function findSymbol (
  originSymbol,
  originScript,
  destinationScript
) {
  for (var i = 0; i < dictionnary.length; i++) {
    var char = dictionnary[i];
    if (char[originScript] === originSymbol) {
      return char[destinationScript]
    }
  }
  return false // if not found
}



function translate (
  text, 
  originScript, 
  destinationScript
 ) {
   var cur = 0;
   var translated = "";
   var maxLength = max[originScript]
   while (cur < text.length) {
    var testedPhoneme;
    var symbol = false;
    for (var length=maxLength; length > 0; length--) {
      testedPhoneme = text.substr(cur, length);
      symbol = findSymbol(
        testedPhoneme, 
        originScript,
        destinationScript
      )
      if (symbol) {
        break; // stop the loop
      }
    }
    if (symbol) {
      translated += symbol;
      cur += testedPhoneme.length;
    }
    else {
      translated += text[cur];
      cur++;
    }
  }
  return translated
}

var textareas = []; // the list of your textareas

function addTextArea(element, originScript) {
  textareas.push({
    element: element,
    script: originScript
  })
  element.addEventListener("input", function (e) {
    signalTextChanged(element, originScript)
  });
}

function signalTextChanged (
  originElement, 
  originScript
) {
  var originText = originElement.value;
  textareas.forEach(function (textarea) {
    if (textarea.element !== originElement) {
      var translated = translate(
        originText,
        originScript,
        textarea.script
      )
      textarea.element.value = translated;
    }
  })
}

// connect your textareas below !!
addTextArea(
  document.querySelector("#latin"), 
  "latin"
);
addTextArea(
  document.querySelector("#japanese"), 
  "japanese"
);
addTextArea(
  document.querySelector("#emoji"), 
  "emoji"
);
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">

    <script type="text/javascript">

    </script>

  </head>
  <body>  
    <center>

      <h1>Latin to foreign script converter 3</h1>
      <p>type in u, ku, tsu in the FIRST panel</p>

      <textarea
                id="latin"
                autofocus=""
                placeholder="type text in latin ! (u ku or tsu)"
                rows="10" 
                style="width:300px"></textarea>    

      <textarea  
                id="japanese"
                rows="10"
                placeholder="type text in japanese !"
                style="width:300px"></textarea>    

      <textarea 
                id="emoji"
                rows="10" 
                placeholder="type text in emojis !!"
                style="width:300px"></textarea>
    </center>



    </center>
  </body>
</html>

Upvotes: 1

Shuki
Shuki

Reputation: 41

I'm not sure if I fully understand what you're trying to achieve here

There are some duplications in your code, what if you'll have 10 fields for output, will you create a special function for each of them?

Try to simplify things.

One way would be to loop through all of your lists as follows:

  1. Put all your conversation in a list

    var lists = [conversion, conversion2];
    
  2. Add isInNextList function to check if your text is a key in the next list

    function isInNextList(index, key) {
         if (lists.length < index) {
             return false;
         }
         return Object.keys(lists[index]).includes(key);
     }
    
  3. change your onInputTextChange function as follow:

     function onInputTextChange(txt) {
         var index = 0;
         var text = txt;
         while (isInNextList(index, text)) {
             var outputTextareaElem = document.getElementById(
                 'output_textarea_' + index
             );
             var div = document.createElement('div');
             text = lists[index][text]; //next key
             index++;
             div.innerHTML = text;
             outputTextareaElem.value = div.innerText;
         }
     }
    
  4. change your output textarea's ids to contain the index

             id="output_textarea_0"
             id="output_textarea_1"
    

There are other improvements that can be made like: Creating the output fields dynamically, Clear output fields etc.

Upvotes: 1

Related Questions