0

I am trying to make a function that will take a character, which is the value of the key pressed on the keyboard, convert it to another special character, and insert it into a particular input field (something like simulating another keyboard layout).

Example:

  1. User type x on keyboard
  2. The function takes this character and converts it into
  3. Than function insert this character into a particular input field

I made a function which converts those special characters:

$("input").keydown(function(e){
    var keyCharacter = e.key;
});

var replaceFrom = [/A/, /i/, /a/, /s/, /z/, /S/, /q/, /H/, /x/, /X/, /T/, /D/];
var replaceTo = ["ꜣ", "j", "ꜥ", "s", "z", "š", "q", "ḥ", "ḫ", "ẖ", "ṯ", "ḏ"];

function transliterationConverter(user_input, transliteration_schema_to_replace, transliteration_schema_for_replace) {
    for (i = 0; i < transliteration_schema_to_replace.length; i++) {
        user_input = user_input.replace(new RegExp(transliteration_schema_to_replace[i], "g"), transliteration_schema_for_replace[i]);
    }
    return user_input;
}

var convertedKeyCharacter = transliterationConverter(keyCharacter, replaceFrom, replaceTo);

// Character typed by user: x
// Desired result in input field: ḫ

P.S. I am not happy with a solution that includes taking value from the input field and then converts its characters to other ones, because if that happening, the user can see the "conversion process" that is happening in half of a second.

Boris J.
  • 67
  • 7
  • I need that function for converting user input into special transliteration letters used by Egyptologists for representing hieroglyphs as letters. – Boris J. Oct 05 '19 at 18:55
  • I don't need a translation in another field. I need that everything is happening in the same field because the user should enter those special characters in one field and submit the form. – Boris J. Oct 05 '19 at 19:16

2 Answers2

1

In case of hiding not converted value from user, you gotta use event keypress,prevent default action and change each character manually, then append it to input value

UPDATED CHECK MY SOLUTION!!!

example:

let element = document.querySelector('#something');
const replaceFrom = {'A': 'ꜣ', 'i': 'j', 'a':'ꜥ' , 's': 's', 'z':'z', 'S': "š", 'q': "q", 'H': "ḥ"}



element.addEventListener('keypress',function(event) {
  event.preventDefault();
  let location  = this.selectionStart,
      result = '',newArr = [];
  let arr =  this.value.split('');
  let char = (typeof replaceFrom[event.key] == "undefined")?event.key:replaceFrom[event.key];
  arr.forEach((elem,index)=>{
    if(index == location ){
      newArr[index] = char;
      newArr[index+1] = elem;
    }
    else if(index>location)
      newArr[index+1] = elem;
    else
      newArr[index] = elem;
  })
  if(arr.length == 0)
    newArr[0] = char;
  else if(location == arr.length){
      newArr[location] = char;  
  }

  newArr.forEach(ch=>{
    result += ch;
  })
  this.value = result;
  this.selectionStart = location+1;
  this.selectionEnd = location+1;
})
<input id="something">
0

First of all, you don't need jQuery, in my example I use window.onload to attach a function to be run after the page load.

On page load, it will call bindEvents, this function is in charge of binding events on element within the DOM (which is now loaded).

Then if you only need to translate, you can make the translation readonly, and you can convert all the values at once.

I have replaced your two arrays with an object behaving like a Map, because it is a 1 to 1 relationship and it is easier to maintain and to read.

window.onload = function init() {
  bindEvents();
}

function bindEvents() {
  document.querySelector('textarea[name="original"]').addEventListener('keyup', updateTranslation, true);
}


const translationMap = {
  A: 'ꜣ',
  i: 'j',
  a: 'ꜥ',
  s: 's',
  z: 'z',
  S: 'š',
  q: 'q',
  H: 'ḥ',
  x: 'ḫ',
  X: 'ẖ',
  T: 'ṯ',
  D: 'ḏ'
}

function updateTranslation(e) {
  const txtArea = document.querySelector('textarea[name="original"]');
  let txt = txtArea.value;
  let newTxt = '';
  
  for(let i = 0; i < txt.length; i += 1) {
    newTxt += translationMap[txt[i]] ? translationMap[txt[i]] : txt[i];
  }
  
  txtArea.value = newTxt;
}
h3 {
  text-align: center;
}

textarea {
  width: 100%;
  height: 150px;
  margin: 5px;
}
<div class="half-width">
  <h3>Input into special transliteration letters used by Egyptologists for representing hieroglyphs as letters</h3>
  <textarea name="original" placeholder="type here"></textarea>
</div>
Dimitri Kopriwa
  • 13,139
  • 27
  • 98
  • 204
  • It should allow the user to correct his input. It should behave like a regular field, but with character conversion. – Boris J. Oct 05 '19 at 19:26
  • @BorisJ. I have made the whole in the textarea for the translation, now you will need to add some tuning, for selecting and not losing the cursor position, for navigating with the keys, etc. This is due because you are rerendering the textarea while you are typing, forcing the cursor position to be set after the text upon replace. – Dimitri Kopriwa Oct 05 '19 at 19:49
  • It is a good solution. The only thing I don't like is that you can see the translation process. First, the character you typed appears, and then it is switched with another one. If only we could skip that step - that translation happens before character appears in the field - if it is possible. – Boris J. Oct 05 '19 at 19:49
  • http://stackoverflow.com/questions/263743/how-to-get-the-caret-column-not-pixels-position-in-a-textarea-in-characters https://stackoverflow.com/questions/34968174/set-text-cursor-position-in-a-textarea – Dimitri Kopriwa Oct 05 '19 at 19:49
  • Thank you for your help. I will try to improve your function to include those cursor positions. – Boris J. Oct 05 '19 at 19:51
  • Sorry, I am out of time, I think in your case it would be more adapted to use a custom component rather than a textarea, you need to reprogram a textarea with a different behavor. – Dimitri Kopriwa Oct 05 '19 at 19:51
  • I don't think it is possible to prevent the text from being displayed in a textarea, maybe you should wait for some other people feedback. Generally I try to avoid reflowing a component that I am currently editing. – Dimitri Kopriwa Oct 05 '19 at 19:52
  • No problem, you did quite a lot to help me. – Boris J. Oct 05 '19 at 19:52
  • Maybe put an invisible textarea directly on top of the translated textarea. Of course, you'd probably have to use a fixed-width font for this to be effective.... and then there's scrolling to deal with. But just throwing out ideas. – bob Oct 06 '19 at 00:59