2

I want to insert a HTML tag in a keypress event. I am new to jQuery and JavaScript, and I've also searched for this thing, but got no answer for this thing

I know about the append and selectionStart methods but i want to insert at the position of text cursor

For E.g., if i type the letter 'a', it should send <img src='a.png'> to the div, at the cursor position

$("#textcontent").contentEditable = "true";

$(document).ready(function(){
  $("#textcontent").keydown(function(event){ 
    $("#textcontent").append("<img src='" + event.key +".png'>");

But this (JS append code at the top) is not I want, but I want to insert a HTML tag at the current text cursor position

My HTML:

<div class="textcontent" contenteditable="true">
  <img src='h.png'>
  ... // more image tags goes here
</div>

Can anybody pls give some answers for this problem?

Ghost Ops
  • 1,710
  • 2
  • 13
  • 23
  • 1
    Does this answer your question? [How to insert text into the textarea at the current cursor position?](https://stackoverflow.com/questions/11076975/how-to-insert-text-into-the-textarea-at-the-current-cursor-position) – AndrewL64 Aug 18 '21 at 08:05
  • Nah dude, i wanted to insert HTML tag inside the same
    tag, which means i wanted to send a bunch of characters in just a single character input. sry it's not what i want.
    – Ghost Ops Aug 18 '21 at 09:17

2 Answers2

1

Check this out:

image 1

image 2


$("#textcontent").keydown(function(event) {
  if (event.key === "Backspace") return; // allow backspace to clear image
  if (!/^[a-zA-Z0-9]{1,1}$/.test(event.key)) return false; // just allow a-z and 0-9

  const position = document.getSelection().anchorOffset; // get position
  const newElement = $(`<img alt="${event.key}" src="https://eu.ui-avatars.com/api/?name=${event.key}">`); // create new element
  const element = [...$("#textcontent img")][position]; // get previous element on index "position"
  if (element)
    textcontent.insertBefore(newElement.get(0), element); // prepend element
  else $("#textcontent").append(newElement); // append element
  
  /* OPTIONAL! place caret at the end */
  textcontent.focus();
  const range = document.createRange();
  range.selectNodeContents(textcontent);
  range.collapse(false);
  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
  /**/
  
  return false; // cancel event to avoid text inside div
});
#textcontent {
  border: 2px solid gray;
  padding: 10px;
  border-radius: 10px;
}
img {
  margin-left: 7px;
  width: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="textcontent" contenteditable="true"></div>
stacj
  • 1,103
  • 1
  • 7
  • 20
  • Its working very well, but it does the same for every key press, like, if i press left arrow button, it appends image with content 'AR', i can ignore that by some way, but i can't do any backspace, it appends 'BA', i also wanted to do backspace from in-between the images, any idea? pls help – Ghost Ops Aug 18 '21 at 09:36
  • 1
    Sure your capturing every single keypress event (Like windows key, arrows, meta, numbers, letters, ...). You need custom logic to handle these, maybe make use of a whitelist which of the keys are allowed! – stacj Aug 18 '21 at 09:37
  • yeah, thats what i am doing right now, but don't know how to deal with the optional code you gave, i commented the optional code and it prepends from the selectionStart Edit: now it works really well, thanks! Now i've to think how to filter some home, end, and delete keys and do their actual functions on the images... do u have any idea? – Ghost Ops Aug 18 '21 at 09:42
  • 1
    Using the code just moves the caret to the end of the line to allow you write a word without placing the caret to the end every single time! If you comment it out you need to do it yourself! – stacj Aug 18 '21 at 09:44
  • Hey, i just did some updates on your code, but i don't know how to deal with the enter key. pls help... – Ghost Ops Aug 19 '21 at 12:05
0

I've made some changes on @jns's code and this is what i've came up with...

Added the function to use lowercase characters, space and also for some other symbols...

Thank you @jns!

$("#textcontent").keydown(function(event) {
  if ((event.key === "Backspace")||(event.ctrlKey)||(event.altKey)||(event.keyCode == 46)||(event.which>=33 && event.which <=40)) return; // Allow other keys to do their normal functions (not for Enter key)
  if (!/^[a-zA-Z0-9\/`~=\[\]'\\; ]$/.test(event.key)) return false; // Just allows A-Z, a-z, 0-9, and also characters like `~=[];'\/
  var letter_name = event.key;
  var uppercase = "false";
  if (event.key === ' ' || event.key === 'Spacebar') // To add spacebar input feature ('Spacebar' for IE9 and Firefox < 37)
    letter_name = '';
  else
    letter_name = event.key;
  if (/^[A-Z]$/.test(letter_name)) // To chech whether its an uppercase letter
    uppercase = "true";
  else
    uppercase = "false";
  const position = document.getSelection().anchorOffset; // get position
  const newElement = $(`<img alt="${letter_name}" src="https://eu.ui-avatars.com/api/?uppercase=${uppercase}&name=${letter_name}">`); // create new element
  const element = [...$("#textcontent img")][position]; // get previous element on index "position"
  if (element)
    textcontent.insertBefore(newElement.get(0), element); // prepend element
  else $("#textcontent").append(newElement); // append element

  /* OPTIONAL! place caret at the end */
  textcontent.focus();
  const range = document.createRange();
  range.selectNodeContents(textcontent);
  range.collapse(false);
  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
  /**/

  return false; // cancel event to avoid text inside div
});
#textcontent {
  border: 2px solid gray;
  padding: 10px;
  border-radius: 10px;
}

img {
  margin-left: 7px;
  width: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="textcontent" contenteditable="true"></div>
Ghost Ops
  • 1,710
  • 2
  • 13
  • 23