JSFiddle - React, Tailwind, and code Playground

by electronixg

HTML

<div class="emoji-box">
<span>&#128578;</span>
<img src="https://upload.wikimedia.org/wikipedia/commons/0/02/Red_Circle%28small%29.svg" class="image-emoji">
</div>

<div class="input-field" placeholder="Tell me something..." contentEditable="true"></div>

CSS

html {  
  font-size: 62.5%; 
}

.image-emoji { 
  max-width: 1.8rem;
  max-height: 1.8rem;
  border-radius: 100%;
  padding: 0;
  margin: 0 0.15rem 0;  
}


.input-field {
  word-break: break-all;
  font-size:1.6rem;
  min-height: 3rem;
  max-height: 20rem;
  width: 60%; 
  margin: 0.5rem;
  padding: 1rem 6rem 1rem 4rem;
  border: 2px solid #e6e6e6;
  border-radius: 0.5rem;
  outline: none;
  overflow-y: auto;  
  line-height: 2.5rem;  
}

.input-field img {
  vertical-align: middle;
}


[contenteditable="true"]:empty:before {  
  content: attr(placeholder);
  pointer-events: none;
  display: block; /* For Firefox */
}


.emoji-box {
  display: flex;
  align-items: center;  
  font-size:1.6rem;
  background: white;
  border: 0.2rem solid #eee;
  border-radius: 0.5rem;
  height: 3rem;
  width: 60%;   
  padding: 1rem 6rem 1rem 4rem;
  margin: 0.5rem;
  color: #183153;
  cursor: pointer;
  overflow-y: auto;  
}

JavaScript

const emojiBox = document.querySelector(".emoji-box");
const inputField = document.querySelector(".input-field");
const matchHtmlTagsRegex = /<(\s|\/?)*([a-z]|!--|!doctype)+[^<>]*>/gi;

let pos;

function getCaretIndex(element) {
  let position = 0;
  const isSupported = typeof window.getSelection !== "undefined";
  if (isSupported) {
    const selection = window.getSelection();
    if (selection.rangeCount !== 0) {
      const range = window.getSelection().getRangeAt(0);
      const preCaretRange = range.cloneRange();
      //range.deleteContents();
      preCaretRange.selectNodeContents(element);
      preCaretRange.setEnd(range.endContainer, range.endOffset);
      position = preCaretRange.toString().length;
    }
  }
  return position;
}

inputField.addEventListener("click", () => {
  pos = getCaretIndex(inputField);
});

emojiBox.addEventListener("click", (e) => {
  let emoji = null;
  let isImage = null;
  let emojiImage = null;
  let removeBR = null;
  let startPos = (endPos = 0);
  if (pos){
  starPos = enPos = pos  
  console.log("pos: " + starPos);
   
  }
  console.log(e.target.outerHTML);
  let htmlLength;
  
  if (e.target != e.currentTarget) {    
    removeBR = inputField.querySelector("br");
    if (removeBR) {
      removeBR.outerHTML = "";
    }

    if (
      e.target.tagName.toLowerCase() === "img" &&
      e.target.classList.value.toLowerCase() === "image-emoji"
    )
      isImage = true;

    if (isImage) {
      emojiImage = e.target;
    } else {
      emoji = e.target;
    }
  }
  
  
 /* if (matchHtmlTagsRegex.test(inputField.innerHTML)) {
      htmlLength = inputField.innerHTML.replace(
        matchHtmlTagsRegex,
        ""
      ).length;
      console.log("match: " + htmlLength);
  }
  else
  {*/
  
  requestAnimationFrame(() => {
  htmlLength = inputField.innerHTML.length;
  console.log("HTML LENGTH: " + htmlLength);
 // }
 }); 


  if (emoji) {
     inputField.innerHTML =
      inputField.innerHTML.substring(0, startPos) +
     ...