JSFiddle - React, Tailwind, and code Playground
HTML
<div class="outer">
<div class="border">
<div class="sel"></div>
<div class="dtextbox"></div>
<input type="text" class="textbox" maxlength="40">
<div class="cursor"></div>
</div>
</div>
<div class="sizec"></div>
<div class="sizesel"></div>
CSS
.outer {
position: relative;
width: 400px;
margin: 10px;
}
.outer .border {
position: relative;
border: 1px solid #09d;
padding: 4px 5px;
}
.outer .textbox {
top: 0;
left: 0;
width: 100%;
height: 20px;
font-family: arial;
font-size: 16px;
padding: 0;
border-width: 0;
opacity: 0;
}
.outer .sel {
position: absolute;
top: 4px;
left: 5px;
width: 20px;
height: 20px;
font-family: arial;
font-size: 16px;
padding: 0;
border-width: 0;
color: #222;
background-color: #AACCFF;
display: none;
}
.outer .dtextbox {
position: absolute;
top: 4px;
left: 5px;
width: 100%;
height: 20px;
font-family: arial;
font-size: 16px;
padding: 0;
border-width: 0;
color: #222;
}
.outer .cursor {
overflow: hidden;
position: absolute;
cursor: pointer;
border-left: 2px solid black;
top: 4px;
left: 5px;
height: 20px;
}
/* used for text size calculation */
/* ensure this has same font settings */
.sizec {
font-family: arial;
font-size: 16px;
/*visiblity: hidden; */
opacity: 0.75;
position: absolute;
right: 0;
bottom: 0;
border: 1px solid #000;
white-space: pre;
}
.sizesel {
font-family: arial;
font-size: 16px;
/*visiblity: hidden; */
opacity: 0.75;
position: absolute;
left: 0;
bottom: 0;
border: 1px solid #000;
white-space: pre;
}
JavaScript
var textbox = $('.outer .textbox');
var dtextbox = $('.outer .dtextbox');
var cursor = $('.outer .cursor');
var sel = $('.outer .sel');
var sizec = $('.sizec');
var sizesel = $('.sizesel');
var mdown = false;
var cursorTimer;
var hasFocus = false;
function toggleCursor() {
if(hasFocus) {
if(cursor.is(':visible')) cursor.hide(); else cursor.show();
}
setTimeout(toggleCursor, 500);
}
toggleCursor();
function doGetCaretPosition (ctrl) {
var CaretPos = 0;
if (ctrl.selectionStart || ctrl.selectionStart == '0') {
CaretPos = ctrl.selectionStart;
}
return (CaretPos);
}
function updateCursorPos() {
var c = doGetCaretPosition(textbox[0]);
dtextbox .text(textbox.val());
cursor.css('left', (5+sizec.text(textbox.val().substring(0, c)).width()) + 'px');
drawSelection();
}
function drawSelection() {
// check if selection is there, if so draw selection
var t = textbox[0];
if(t.selectionEnd != t.selectionStart) {
var s = textbox.val();
var l = 5+sizesel.text(s.substring(0, t.selectionStart)).width();
var w = sizesel.text(s.substring(t.selectionStart, t.selectionEnd)).width();
sel.css({left: l+'px', width: w+'px'}).show();
}
else {
sel.hide();
}
}
textbox.focus(function() {
hasFocus = true;
}).blur(function() {
hasFocus = false;
}).keypress(function() {
setTimeout(updateCursorPos, 0);
}).mouseup(function() {
setTimeout(updateCursorPos, 0);
mdown = false;
}).mousedown(function() {
setTimeout(updateCursorPos, 0);
mdown = true;
}).mousemove(function() {
if(mdown == true) {
setTimeout(updateCursorPos, 0);
}
}).focus();