I had the following Problem. The objective was to make an text-input for an E-Mail thats is always showing the the same appendix.
For example Max.Mustermann@mail.de.
Requirements:
The input field:
<input type="text" class="form-control" id="mailAddress" placeholder="Max.Mustermann@mail.de" maxlength="64">
So how is this possible?
Adding a div and position it over the text input will do the trick. Another hidden div is used to measure the content length and position the appendix accordingly.
The following example migth not be perfect but will do the job:
(feel free to improve the solution)
const mailAddress = document.getElementById("mailAddress")
const appendix = document.getElementById("appendix")
const hiddenDiv = document.getElementById("hiddenDiv")
window.addEventListener('resize', () => {
hideOverflow(mailAddress.value)
})
mailAddress.addEventListener('keydown', styleAppendixDown)
mailAddress.addEventListener('keyup', styleAppendixUp)
mailAddress.addEventListener("paste", (event) => {
let paste = (event.clipboardData || window.clipboardData).getData("text");
let selection = getSelectedText(mailAddress)
styleAppendixPaste(paste, selection)
});
function getSelectedText(elem) { // only allow input[type=text]/textarea
if (elem.tagName === "TEXTAREA" ||
(elem.tagName === "INPUT" && elem.type === "text")) {
return elem.value.substring(elem.selectionStart,
elem.selectionEnd);
}
return null;
}
function styleAppendixPaste(paste, selection) {
// measure the width
hiddenDiv.textContent = paste
let pasteWidth = hiddenDiv.clientWidth
// measure the width
hiddenDiv.textContent = selection
let selectionWidth = hiddenDiv.clientWidth
// measure the width
hiddenDiv.textContent = mailAddress.value
let textWidth = hiddenDiv.clientWidth
if (mailAddress.value.length === 0) {
appendix.style.left = (textWidth + pasteWidth + 13 - selectionWidth) + 'px'
} else {
appendix.style.left = (textWidth + pasteWidth + 13 - selectionWidth) + 'px'
appendix.style.display = 'block'
appendix.style.color = '#495057'
// Delete Selected Text
let pre = mailAddress.value.substring(0, mailAddress.selectionStart)
let post = mailAddress.value.substring(mailAddress.selectionEnd, mailAddress.length)
let finalText = pre + paste + post;
hideOverflow(finalText)
}
}
function styleAppendixDown(e) {
let keyCode = e.keyCode
let keyString = ''
if (e.key) {
if (e.key.length <= 1) {
keyString = e.key
}
if (keyCode === 32) {
keyString = ''
}
}
if (mailAddress.value.length === 0) {
appendix.style.display = 'none'
}
let cursorPosition = mailAddress.selectionStart
if (e.key == 'Backspace' || keyCode === 8) {
if (cursorPosition >= 1) {
let prevKey = mailAddress.value.substring(cursorPosition - 1, cursorPosition)
hiddenDiv.textContent = prevKey
let keyWidth = hiddenDiv.clientWidth
// measure the width
hiddenDiv.textContent = mailAddress.value
let textWidth = hiddenDiv.clientWidth
appendix.style.left = (textWidth - keyWidth + 13) + 'px'
appendix.style.display = 'block'
appendix.style.color = '#495057'
}
hideOverflow(mailAddress.value)
}
// Remove Spaces so Spaces don't break the Styling
if (keyCode === 32) {
let value = mailAddress.value
mailAddress.value = value.toString().replace(" ", "")
}
// Move the div
moveDivDown(keyCode, keyString)
}
// Move the @mail.de div Based on Input
function moveDivDown(keyCode, keyString) {
let keyWidth
// measure the width
hiddenDiv.textContent = keyString
keyWidth = hiddenDiv.clientWidth
// measure the width
hiddenDiv.textContent = mailAddress.value
let textWidth = hiddenDiv.clientWidth
if (mailAddress.value.length === 0) {
appendix.style.left = (textWidth + keyWidth + 13) + 'px'
} else {
appendix.style.left = (textWidth + keyWidth + 13) + 'px'
appendix.style.display = 'block'
appendix.style.color = '#495057'
hideOverflow(mailAddress.value + keyString)
}
}
function styleAppendixUp(e) {
let keyCode = e.keyCode
if (mailAddress.value.length !== 0) {
// show Appendix
appendix.style.display = 'block'
appendix.style.color = '#495057'
}
if (mailAddress.value.length === 0) {
appendix.style.display = 'none'
}
// Check Backspace
if (keyCode === 8) {
backspaceUp()
}
// Remove Spaces again so Spaces don't break the Styling
if (keyCode === 32) {
let value = mailAddress.value
mailAddress.value = value.toString().replace(" ", "")
}
if (mailAddress.value.length === 0) {
appendix.style.display = 'none'
}
// Move the div again
hiddenDiv.textContent = mailAddress.value
let textWidth = hiddenDiv.clientWidth
appendix.style.left = (textWidth + 13) + 'px'
hideOverflow(mailAddress.value)
}
function backspaceUp() {
let cursorPosition = mailAddress.selectionStart
if (cursorPosition >= 1) {
// measure the width
hiddenDiv.textContent = mailAddress.value
let textWidth = hiddenDiv.clientWidth
appendix.style.left = (textWidth + 13) + 'px'
appendix.style.display = 'block'
appendix.style.color = '#495057'
}
hideOverflow(mailAddress.value)
}
function hideOverflow(text) {
hiddenDiv.textContent = text;
let textWidth = hiddenDiv.clientWidth
hiddenDiv.textContent = appendix.textContent
let appendixWidth = hiddenDiv.clientWidth
let maxWidth = mailAddress.clientWidth
// hide Overflow
if (textWidth + appendixWidth >= (maxWidth - 8)) {
let calcWidth = maxWidth - textWidth
if (calcWidth < 20) {
appendix.style.width = '0'
} else {
calcWidth = calcWidth - 24
appendix.style.width = calcWidth + 'px'
}
} else {
appendix.style.width = 'fit-content'
}
}
function focusMailAddress() {
mailAddress.focus()
}
#mailAddress {
z-index: 1;
}
#appendix {
position: absolute;
margin-top: 14px;
top: 0;
left: 159px;
z-index: 9;
height: fit-content;
width: fit-content;
color: grey;
white-space: nowrap;
overflow: hidden;
text-overflow: fade;
display: none;
}
#hiddenDiv {
width: auto;
display: inline-block;
visibility: hidden;
position: fixed;
overflow: auto;
}
#parent {
position: relative;
width: 100%;
}
body {
margin: 0;
font-family: OpenSansRegular, Arial, Helvetica, sans-serif;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #58595b;
text-align: left;
background-color: #fff;
}
.form-control {
display: block;
width: 100%;
height: calc(1.5em + 0.75rem + 2px);
padding: 0.375rem 0.75rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
<div id="parent">
<input type="text" class="form-control" id="mailAddress"
placeholder="Max.Mustermann@mail.de" maxlength="64">
<div id='appendix' unselectable="on" contenteditable="false" onclick="focusMailAddress()"> @mail.de </div>
<div id="hiddenDiv"></div>
</div>