javascript - преобразовать буквенный символ из события клавиатуры в другой символ и вставить этот новый символ в поле ввода (онлайн-раскладка клавиатуры)

Я пытаюсь создать функцию, которая будет принимать символ, являющийся значением клавиши, нажатой на клавиатуре, преобразовывать его в другой специальный символ и вставлять в определенное поле ввода (что-то вроде имитации другой раскладки клавиатуры).

Пример:

  1. Введите x на клавиатуре
  2. Функция берет этот символ и преобразует его в
  3. Чем функция вставляет этот символ в определенное поле ввода

Я сделал функцию, которая преобразует эти специальные символы:

$("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. Меня не устраивает решение, которое включает в себя получение значения из поля ввода, а затем преобразование его символов в другие, потому что, если это произойдет, пользователь может увидеть «процесс преобразования», который происходит за полсекунды.


person Boris J.    schedule 05.10.2019    source источник
comment
Мне нужна эта функция для преобразования пользовательского ввода в специальные буквы транслитерации, используемые египтологами для представления иероглифов в виде букв.   -  person Boris J.    schedule 05.10.2019
comment
Мне не нужен перевод в другой области. Мне нужно, чтобы все происходило в одном поле, потому что пользователь должен ввести эти специальные символы в одно поле и отправить форму.   -  person Boris J.    schedule 05.10.2019


Ответы (2)


В случае сокрытия не преобразованного значения от пользователя вы должны использовать событие keypress, предотвратить действие по умолчанию и изменить каждый символ вручную, а затем добавить его к входному значению.

ОБНОВЛЕНО ПРОВЕРЬТЕ МОЕ РЕШЕНИЕ!!!

пример:

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">

person Иван Яковлев    schedule 05.10.2019
comment
Я не понимаю вашего ответа. - person Boris J.; 05.10.2019
comment
@user3120612 user3120612 проверьте мой ответ еще раз - person Иван Яковлев; 05.10.2019
comment
Он отлично работает с преобразованием символов, но не работает, когда я хочу вставить новый символ между существующими или если я выбираю часть строки и пытаюсь заменить ее другим символом. Кроме того, он всегда ставит курсор в конец, когда набирается буква. - person Boris J.; 05.10.2019
comment
Чтобы указать или получить положение выделенного текста внутри области ввода или текста, используйте свойства selectionStart и selectionEnd. - person Иван Яковлев; 06.10.2019
comment
я исправил первую проблему и думаю, что вы можете решить следующую проблему самостоятельно =) - person Иван Яковлев; 06.10.2019

Прежде всего, вам не нужен jQuery, в моем примере я использую window.onload для присоединения функции, которая будет запускаться после загрузки страницы.

При загрузке страницы она вызовет bindEvents, эта функция отвечает за привязку событий к элементу внутри DOM (который сейчас загружен).

Затем, если вам нужно только перевести, вы можете сделать перевод readonly, и вы можете преобразовать все значения сразу.

Я заменил ваши два arrays объектом, ведущим себя как Map, потому что это отношение 1 к 1, и его легче поддерживать и читать.

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>

person Dimitri Kopriwa    schedule 05.10.2019
comment
Это должно позволить пользователю исправить свой ввод. Оно должно вести себя как обычное поле, но с преобразованием символов. - person Boris J.; 05.10.2019
comment
@BorisJ. Я сделал все в текстовой области для перевода, теперь вам нужно будет добавить некоторые настройки, для выбора и сохранения позиции курсора, для навигации с помощью клавиш и т. д. Это связано с тем, что вы перерисовываете текстовую область, пока вы ввод, принудительно устанавливая позицию курсора после текста при замене. - person Dimitri Kopriwa; 05.10.2019
comment
Это хорошее решение. Единственное, что мне не нравится, так это то, что вы можете видеть процесс перевода. Сначала появляется введенный вами символ, а затем он переключается на другой. Если бы мы только могли пропустить этот шаг - этот перевод происходит до появления символа в поле - если это возможно. - person Boris J.; 05.10.2019
comment
comment
Спасибо за помощь. Я постараюсь улучшить вашу функцию, чтобы включить эти позиции курсора. - person Boris J.; 05.10.2019
comment
Извините, у меня нет времени, я думаю, что в вашем случае было бы более адаптировано использовать пользовательский компонент, а не текстовое поле, вам нужно перепрограммировать текстовое поле с другим поведением. - person Dimitri Kopriwa; 05.10.2019
comment
Я не думаю, что возможно предотвратить отображение текста в текстовом поле, возможно, вам следует подождать отзывов других людей. Обычно я стараюсь избегать перекомпоновки компонента, который редактирую в данный момент. - person Dimitri Kopriwa; 05.10.2019
comment
Нет проблем, вы очень много сделали, чтобы помочь мне. - person Boris J.; 05.10.2019
comment
Возможно, поместите невидимую текстовую область прямо поверх переведенной текстовой области. Конечно, вам, вероятно, придется использовать шрифт фиксированной ширины, чтобы это было эффективно... а затем нужно было иметь дело с прокруткой. Но просто выбрасывать идеи. - person bob; 06.10.2019