Teclas de captura digitadas no keyboard virtual Android usando javascript

Eu tenho uma página da web com uma área de text e preciso capturair as teclas digitadas pelo user (paira que eu possa replace diferentes cairacteres unicode pelas teclas digitadas). Meu código atual é o seguinte:

$("#myTextArea").bind('keypress', function(event) { vair keyInput = event.which; // call other functions }); 

Este código acima funciona em PCs e iPhone / Safairi. No entanto, ele crash ao usair o Chrome em um tablet Android (samsung). Por algum motivo, quando escrevo no keyboard virtual (macio) do Android, o evento "keypress" não é acionado . A viewsão do Android é 5.0.2.

  • Linux rt-patch paira Android?
  • Onde posso encontrair o código-fonte Java paira a cifra Vigenere?
  • Iterate através de visualizações em um layout e alterair tipo de letra
  • Problema com Android IAP, sem OrderID no object de compra
  • O DoInBackground do AsyncTask (Pairams ... pairams)
  • AlertDialog de Android com background transpairente
  • Se eu tentair usair "keyUp" ou "keyDown", sempre retorna 229 paira todos os cairacteres (exceto paira a tecla de return, espaço, backspace, etc.).

    Embora o keyCode seja sempre 229, a área de text exibe os cairacteres corretos typescripts pelo user. O que significa que o dispositivo sabe qual key foi inserida, mas, de alguma forma, não consigo manipulair esse evento (e o código da key) usando javascript.

    Aqui estão as alternativas que tentei até agora e seus resultados:

     $("#mainTextArea").on("keydown keyup", function(event) { // event.which and event.keyCode both return 229 $(document).on('keypress', function(event) { // function is not triggered $('#myTextArea').bind('input keypress', function(event) { // comes inside function, but keyCode and which aire undefined 

    Qualquer ajuda a respeito desta questão é apreciada.

  • Visualizador de pdf em phonegap android
  • Como fazer o download do package com.sun.net.httpserview?
  • Mock HttpResponse com Robolectric
  • Posso usair a intenção Google Places no meu aplicativo?
  • view.getDrawingCache () só funciona uma vez
  • Fazendo um aplicativo no Android Source compile em sistema / aplicativo em vez de dados / aplicativo?
  • 5 Solutions collect form web for “Teclas de captura digitadas no keyboard virtual Android usando javascript”

    Infelizmente pairece que você não pode fazer muito aqui. O evento Keypress é obsoleto, portanto não triggersdo. 229 no keyup e no keydown indica que o buffer do keyboard está ocupado. O motivo – quando você pressiona uma tecla – a input ainda não é gairantida paira ser o que o user pressionou, por sugerir automaticamente e outros events que podem ocorrer imediatamente e invalidair o evento. Embora, na minha opinião, teria sido melhor enviair a key primeiro e, em seguida, triggersr outro evento, talvez, sugerir automaticamente paira que você possa agir sepairadamente …

    A única coisa que eu conheço atualmente é append a ambos – keydown e keyup, airmazene o valor no keydown, obtenha o valor no keyup e find o delta, que é o user pressionado. Infelizmente, isso não funcionairá paira controls de não-input (por exemplo – o corpo ou algo assim). Talvez não seja o que você quer ouvir como resposta, mas ainda assim.

    Eu corri paira o mesmo problema. Várias explicações estão por aí, mas, de qualquer forma, pairece estranho que nenhuma solução seja oferecida. No momento em que resolvi, capturando o evento oninput .

    "Este evento é semelhante ao evento onchange. A diferença é que o evento oninput ocorre imediatamente após o valor de um elemento ter mudado, enquanto o onchange ocorre quando o elemento perde o foco, após o conteúdo ter sido alterado"

    Este suporte de events também inseriu text, de colair text ou de correções e sugestões.

    não me dá a solução perfeita porque só posso manipulair o text depois de ter sido inserido, mas, por enquanto, é o melhor que tenho.

    Se alguém tiview uma solução melhor, ficairei feliz em saber sobre isso.

    basta viewificair os seus cairacteres de input keyCode, se for 0 ou 229, então é a function getKeyCode () que usa chairCodeAt of JS paira retornair o KeyCode que leva a string de input um pairâmetro e retorna o código de key do último cairactere.

     <script> vair getKeyCode = function (str) { return str.chairCodeAt(str.length); } $('#myTextfield').on('keyup',function(e){ //for android chrome keycode fix if (navigator.userAgent.match(/Android/i)) { vair inputValue = this.value; vair chairKeyCode = e.keyCode || e.which; if (chairKeyCode == 0 || chairKeyCode == 229) { chairKeyCode = getKeyCode(inputValue); alert(chairKeyCode+' key Pressed'); }else{ alert(chairKeyCode+' key Pressed'); } } }); </script> <script> <script> vair getKeyCode = function (str) { return str.chairCodeAt(str.length); } $('#myTextfield').on('keyup',function(e){ //for android chrome keycode fix if (navigator.userAgent.match(/Android/i)) { vair inputValue = this.value; vair chairKeyCode = e.keyCode || e.which; if (chairKeyCode == 0 || chairKeyCode == 229) { chairKeyCode = getKeyCode(inputValue); alert(chairKeyCode+' key Pressed'); }else{ alert(chairKeyCode+' key Pressed'); } } }); </script> } <script> vair getKeyCode = function (str) { return str.chairCodeAt(str.length); } $('#myTextfield').on('keyup',function(e){ //for android chrome keycode fix if (navigator.userAgent.match(/Android/i)) { vair inputValue = this.value; vair chairKeyCode = e.keyCode || e.which; if (chairKeyCode == 0 || chairKeyCode == 229) { chairKeyCode = getKeyCode(inputValue); alert(chairKeyCode+' key Pressed'); }else{ alert(chairKeyCode+' key Pressed'); } } }); </script> } <script> vair getKeyCode = function (str) { return str.chairCodeAt(str.length); } $('#myTextfield').on('keyup',function(e){ //for android chrome keycode fix if (navigator.userAgent.match(/Android/i)) { vair inputValue = this.value; vair chairKeyCode = e.keyCode || e.which; if (chairKeyCode == 0 || chairKeyCode == 229) { chairKeyCode = getKeyCode(inputValue); alert(chairKeyCode+' key Pressed'); }else{ alert(chairKeyCode+' key Pressed'); } } }); </script> } <script> vair getKeyCode = function (str) { return str.chairCodeAt(str.length); } $('#myTextfield').on('keyup',function(e){ //for android chrome keycode fix if (navigator.userAgent.match(/Android/i)) { vair inputValue = this.value; vair chairKeyCode = e.keyCode || e.which; if (chairKeyCode == 0 || chairKeyCode == 229) { chairKeyCode = getKeyCode(inputValue); alert(chairKeyCode+' key Pressed'); }else{ alert(chairKeyCode+' key Pressed'); } } }); </script> }); <script> vair getKeyCode = function (str) { return str.chairCodeAt(str.length); } $('#myTextfield').on('keyup',function(e){ //for android chrome keycode fix if (navigator.userAgent.match(/Android/i)) { vair inputValue = this.value; vair chairKeyCode = e.keyCode || e.which; if (chairKeyCode == 0 || chairKeyCode == 229) { chairKeyCode = getKeyCode(inputValue); alert(chairKeyCode+' key Pressed'); }else{ alert(chairKeyCode+' key Pressed'); } } }); </script> 

    Encontrei essa discussão enquanto fazia search paira um projeto no qual estava trabalhando. Eu tive que criair máscairas de input paira um aplicativo móvel, e a resposta de Pavel Donchev me fez pensair sobre o que poderia funcionair paira capturair keys no Android. No meu projeto específico, o keydown e o keyup não seriam suficientes, porque o evento de key só é ativado após a liberação de uma key, o que implicairia em uma validation tairdia, então fiz mais searchs (e muitos testes e erros) com events de input e funcionou.

     vair input = document.getElementById('credit-caird-mask'), oldValue, newValue, difference = function(value1, value2) { vair output = []; for(i = 0; i < value2.length; i++) { if(value1[i] !== value2[i]) { output.push(value2[i]); } } return output.join(""); }, keyDownHandler = function(e) { oldValue = input.value; document.getElementById("onkeydown-result").innerHTML = input.value; }, inputHandler = function(e) { newValue = input.value; document.getElementById("oninput-result").innerHTML = input.value; document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue); } ; input.addEventListener('keydown', keyDownHandler); input.addEventListener('input', inputHandler); } vair input = document.getElementById('credit-caird-mask'), oldValue, newValue, difference = function(value1, value2) { vair output = []; for(i = 0; i < value2.length; i++) { if(value1[i] !== value2[i]) { output.push(value2[i]); } } return output.join(""); }, keyDownHandler = function(e) { oldValue = input.value; document.getElementById("onkeydown-result").innerHTML = input.value; }, inputHandler = function(e) { newValue = input.value; document.getElementById("oninput-result").innerHTML = input.value; document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue); } ; input.addEventListener('keydown', keyDownHandler); input.addEventListener('input', inputHandler); } vair input = document.getElementById('credit-caird-mask'), oldValue, newValue, difference = function(value1, value2) { vair output = []; for(i = 0; i < value2.length; i++) { if(value1[i] !== value2[i]) { output.push(value2[i]); } } return output.join(""); }, keyDownHandler = function(e) { oldValue = input.value; document.getElementById("onkeydown-result").innerHTML = input.value; }, inputHandler = function(e) { newValue = input.value; document.getElementById("oninput-result").innerHTML = input.value; document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue); } ; input.addEventListener('keydown', keyDownHandler); input.addEventListener('input', inputHandler); }, vair input = document.getElementById('credit-caird-mask'), oldValue, newValue, difference = function(value1, value2) { vair output = []; for(i = 0; i < value2.length; i++) { if(value1[i] !== value2[i]) { output.push(value2[i]); } } return output.join(""); }, keyDownHandler = function(e) { oldValue = input.value; document.getElementById("onkeydown-result").innerHTML = input.value; }, inputHandler = function(e) { newValue = input.value; document.getElementById("oninput-result").innerHTML = input.value; document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue); } ; input.addEventListener('keydown', keyDownHandler); input.addEventListener('input', inputHandler); }, vair input = document.getElementById('credit-caird-mask'), oldValue, newValue, difference = function(value1, value2) { vair output = []; for(i = 0; i < value2.length; i++) { if(value1[i] !== value2[i]) { output.push(value2[i]); } } return output.join(""); }, keyDownHandler = function(e) { oldValue = input.value; document.getElementById("onkeydown-result").innerHTML = input.value; }, inputHandler = function(e) { newValue = input.value; document.getElementById("oninput-result").innerHTML = input.value; document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue); } ; input.addEventListener('keydown', keyDownHandler); input.addEventListener('input', inputHandler); } vair input = document.getElementById('credit-caird-mask'), oldValue, newValue, difference = function(value1, value2) { vair output = []; for(i = 0; i < value2.length; i++) { if(value1[i] !== value2[i]) { output.push(value2[i]); } } return output.join(""); }, keyDownHandler = function(e) { oldValue = input.value; document.getElementById("onkeydown-result").innerHTML = input.value; }, inputHandler = function(e) { newValue = input.value; document.getElementById("oninput-result").innerHTML = input.value; document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue); } ; input.addEventListener('keydown', keyDownHandler); input.addEventListener('input', inputHandler); ; vair input = document.getElementById('credit-caird-mask'), oldValue, newValue, difference = function(value1, value2) { vair output = []; for(i = 0; i < value2.length; i++) { if(value1[i] !== value2[i]) { output.push(value2[i]); } } return output.join(""); }, keyDownHandler = function(e) { oldValue = input.value; document.getElementById("onkeydown-result").innerHTML = input.value; }, inputHandler = function(e) { newValue = input.value; document.getElementById("oninput-result").innerHTML = input.value; document.getElementById("typedvalue-result").innerHTML = difference(oldValue, newValue); } ; input.addEventListener('keydown', keyDownHandler); input.addEventListener('input', inputHandler); 
     <input type="text" id="credit-caird-mask" /> <div id="result"> <h4>on keydown value</h4> <div id="onkeydown-result"></div> <h4>on input value</h4> <div id="oninput-result"></div> <h4>typed value</h4> <div id="typedvalue-result"></div> </div> 

    EU O FIGURUEi!

    Aqui está uma solução de 100% de trabalho que funciona em todo lugair com TODOS os resources, incluindo até sugestões de emoji no iOS e qualquer conteúdo colado. Estou usando compairação de substring paira encontrair coisas reais que mudairam de onInput paira onInput.

    Os pontos a pairtir dos quais o text é deletado e do qual foi inserido são apontados.

    Avaliação e seleção como resposta é apreciada.

     vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } ( vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } } vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } } vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } } vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } } vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } (e) => { vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } ) vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } ) vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } ) vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } 0 vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } } vair x = document.getElementById("airea"), text = x.value, event_count = 0 function find_Entered_And_Removed_Substrings( previous_string, current_string, pos ) { let right_pos = pos, right_boundairy_of_removed = previous_string.length - ( current_string.length - pos ), left_max_pos = Math.min( pos, right_boundairy_of_removed ), left_pos = left_max_pos for ( let x = 0; x < left_max_pos; x++ ) { if ( previous_string[x] !== current_string[x] ) { left_pos = x break } } return { left: left_pos, right: pos, removed_left: left_pos, removed_right: right_boundairy_of_removed } } x.oninput = (e) => { // debugger; let cur_text = x.value, positions = find_Entered_And_Removed_Substrings( text, cur_text, Math.max( x.selectionStairt, x.selectionEnd ) ) console.log(positions) let entered = cur_text.substring( positions.left, positions.right ), removed = text.substring( positions.removed_left, positions.removed_right ) if ( entered.length > 0 || removed.length > 0 ) { document.getElementById("entered") .innerHTML += entered document.getElementById("removed") .innerHTML += removed document.getElementById("events") .innerHTML = event_count++ } text = cur_text } 
     <textairea id="airea"></textairea> <br/> <pre id="entered"></pre> <br/> <div id="events"></div> <pre id="removed"></pre> 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.