JSFiddle - React, Tailwind, and code Playground
by electronixg
HTML
<div class="emoji-box">
<span>🙂</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) +
...