Position div immediately to the right of text input-field - javascript

I'm trying to position a div immediately to the right of text being typed in a text input-field. To me, this seems as simple as taking the length of the input's val and positioning the div to that value. However, what is happening is that it is only right after the text when there is 1 character in the input-field. As more and more are typed, the offset becomes larger and larger.
What i'm trying to create is a suggestion box that will complete a word that is being typed.
How can I position this so that on each keyup it is to the right and right next to the input's value?
Here is a js fiddle: http://jsfiddle.net/ugkzdjsy/
And here is how I'm trying to position it on keyup:
$('input').on('keyup', function(){
$('#suggestion').css('left', $(this).val().length+'rem');
});
No matter what units I try, px, em, rem, I get similar results.

You'll have to calculate the width of the text and then set the left property.
Here's a JavaScript function that will do it.
This function creates a span tag gives it the same property as the input tag, appends the input text to the span, then appends the span tag to the DOM and get the width using .offsetWidth.
$('input').on('keyup', function() {
$('#suggestion').css('left', width($(this).val()) + 1 + 'px');
});
function width(text) {
var s = document.createElement('span');
var t = document.createTextNode(text)
s.appendChild(t);
s.id = 'length';
s.style.fontSize = '1.2rem';
s.style.visibily = 'hidden';
s.style.opacity = '0';
var m = document.getElementById('suggestion');
for (i = 0; i < m.children.length; i++) {
if (m.children[i].id == 'length') {
m.removeChild(m.children[i]);
}
}
m.appendChild(s);
return (s.offsetWidth * 0.935 > document.getElementById('inpt').offsetWidth) ? document.getElementById('inpt').offsetWidth : s.offsetWidth * 0.935;
};
html,
body {
font-size: 16px;
}
input {
height: 2.618rem;
font-size: 1.2rem;
}
#suggestion {
height: 1.5rem;
width: 1.5rem;
position: relative;
background: #66bb6a;
color: #000000;
color: rgb(0, 0, 0);
font-family: 'Myriad Pro', 'Open Sans', sans-serif;
top: -35px;
z-index: 2;
overflow: hidden;
transition: all 0.2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="inpt" type="text" val="leonardo" />
<div id="suggestion"></div>

Related

Change word color in input or textarea

For a chat app, I need to change the color of words starting with a special character, #word inside an input tag, i.e:
Hello #John how are you?
the part #John should change color inside the input, i.e:
Hello #John how are you?
It works after it's posted, but that's obviously another code. I want it to highlight words (#mention) by changing its color right in the input or textarea Element.
Color specific text inside a textarea-alike element
One 5y old idea (Highlight syntax in contenteditable) would be to:
let the user type into a contenteditable DIV with transparent color but visible caret, then get and modify the content on the fly as-you-ype to an underlying DIV, used as a markup highlighter.
Basically:
On "input" event get the editable innerHTML, do some String.prototype.replace() with a regular expression that matches #mentions on the contenteditable value and replace i.e: #John with <span class="mention">#John</span>
Write the result as HTML to the underlying (highlighter) DIV element.
This way you're not replacing and creating any child SPAN elements in the area where the user is typing, but actually on the underlying one.
const colorMention = (elText, elPre) => {
elPre.innerHTML = elText.innerHTML.replace(/(?<=^| )#\p{L}+/gu, "<span class='mention'>$&</span>");
};
const scrollMirror = (elText, elPre) => {
elPre.scrollTo(elText.scrollLeft, elText.scrollTop);
};
const handleKey = (ev, elText, elPre) => {
if (ev.key === "Enter" && !ev.shiftKey) {
// prevent Enter key behavior (new-line)
ev.preventDefault();
// Check message to send...
const message = elText.innerHTML;
if (!message.trim()) {
return; // Nothing to submit. Message is empty
}
// YOUR SUBMIT LOGIC GOES HERE:
console.log(message);
// Clear fields:
elText.innerHTML = "";
elPre.innerHTML = "";
} else {
// Any other key: (scroll areas is necessary)
scrollMirror(elText, elPre);
}
};
document.querySelectorAll(".message").forEach(el => {
const elText = el.querySelector(".text");
const elPre = el.querySelector(".pre");
elText.addEventListener("scroll", () => scrollMirror(elText, elPre));
elText.addEventListener("keyup", () => scrollMirror(elText, elPre));
elText.addEventListener("input", () => colorMention(elText, elPre));
elText.addEventListener("keydown", (ev) => handleKey(ev, elText, elPre));
// Init:
colorMention(elText, elPre);
scrollMirror(elText, elPre);
});
* {
margin: 0;
box-sizing: border-box;
}
body {
font: 16px/1.3 sans-serif;
}
.message {
display: block;
border: 1px solid #888;
position: relative;
width: 100%;
border: 1px solid #ccc;
}
.message .pre,
.message .text {
border: 0;
overflow: scroll;
overflow-x: hidden;
font: inherit;
padding: 10px;
height: 5rem;
resize: none;
width: 100%;
white-space: break-spaces;
word-wrap: break-word;
}
/* The overlay contenteditable with transparent text but visible caret */
.message .text {
position: relative;
background: transparent;
outline: none;
/* transparent color */
color: transparent;
/* but visible caret */
caret-color: black;
}
/* The underlaying element with colors */
.message .pre {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* Prevent text selections */
user-select: none;
}
.mention {
color: fuchsia;
}
<div class="message">
<div class="pre"></div>
<div class="text" contenteditable spellcheck="false">Hi #Roko, how are you today?</div>
</div>
<br>
Chat tips:<br> Use <code>#username</code> to mention a user.<br> Use <kbd>Enter</kbd> to send.<br> Use <kbd>Shift</kbd>+<kbd>Enter</kbd> to go to a new line.<br>
Regarding the regular expression for matching mentions:
/(?<=^| )#\p{L}+/gu
here's a Regex101.com example with description, and a related answer.

How to add background color to text inside textbox?

I do not know how to ask this question correctly and I do not know how to find solutions in google because it leads me to how to add entire background color to a textbox which I am not looking for. I am trying to achieve such results like image below:
I want to add background to each text(of course characters) inside a input tag except spaces. User will start typing stuff inside input tag and will apply background color but spaced text won't color.
I do not have any code because I do not know how to do it using css or JS if neccesary. I just have a
<input type="text">
I think it might use only JS but I do not know how to(of course I know JS). How do I achieve that?
You can use div with contentEditable and use little js to append text as span
<div contentEditable></div>
CSS
span {
background-color: red;
margin-right: 2px;
}
div {
border: 1px solid black;
}
var el = document.querySelector("div");
el.addEventListener("blur", () => {
var content = el.textContent;
var contents = content.split(" ");
el.innerHTML = "";
contents.forEach((item) => {
el.innerHTML += `<span>${item}</span>`;
});
});
Something like this
Another method is to overlap the input box with a "mirroring" element. The overlap must be precise, both in layout and text characteristics. Here is a minimal example:
var input = document.getElementById("input"),
mirror = document.getElementById("input-mirror");
input.addEventListener("keyup", function() {
var words = input.value.split(" ").map(function(a) {
var span = document.createElement("span");
span.textContent = a;
return span;
});
mirror.innerHTML = "";
for (let i = 0; i < words.length; i++) {
mirror.append(words[i], " ");
}
});
.container {
display: grid;
}
#input,
#input-mirror {
font: inherit;
box-sizing: border-box;
margin: 0;
border: 1px solid;
padding: 0;
grid-row: 1;
grid-column: 1;
}
#input {
background: transparent;
}
#input-mirror > span {
background: #0f0;
}
<div class="container">
<span id="input-mirror"></span>
<input id="input" type="text" />
</div>

Color text to some fixed limit when I type

I have a textarea. And I am not using any plugin and or API. Implemented the word count that the count increase/decrease when I type.
Basically I want to award points. Say 20 Points if he types in 50 words.
I want that whatever user types the text gets colored but only till 50 words after that words can be black itself.
Means text gets colored while I type till 50 words and remains of same color but remaining words must be normal
JS
$('#content').keyup(function(){
var wordCount = $(this).val().split(' ').length;
if(wordCount <= 50){
$(this).css('color', 'green');
}
});
The following works pretty well in Chrome, Firefox, Opera, Safari, and IE11 (at least).
It overlays a div on the textarea, making sure both elements have the same CSS. A number of CSS properties are important to make this possible, especially word-wrap: pre-wrap, which allows the div to handle multiple spaces correctly.
Using -webkit-text-fill-color: transparent; allows the textarea to display a cursor while making its text invisible. This works in webkit browsers only, but it doesn't kill the functionality in other browsers. In IE, the text is simply darker because it shows the div's text overlaid on top of the textarea's.
Finally, adding pointer-events: none; to the div allows you to position the mouse on the textarea that's behind it.
For the purposes of the snippet, I've set the word count to 5 instead of 50.
Snippet:
$('textarea').on('input', function() {
var word = 0,
lastLetter;
$('#output > span').text('');
this.value.split('').forEach(function(letter, i) {
if (letter === ' ' && lastLetter !== ' ') word++;
lastLetter = letter;
if (word < 5) {
$('#output span:first').append(letter);
} else {
$('#output span:last').append(letter);
}
});
});
$('textarea').focus();
textarea,
#output {
width: 500px;
height: 10em;
padding: 0.2em;
margin: 0.2em;
box-sizing: border-box;
font: 13px arial;
border: 1px solid silver;
white-space: pre-wrap;
}
textarea {
-webkit-text-fill-color: transparent;
overflow: auto;
}
#output {
position: absolute;
pointer-events: none;
z-index: 1;
}
#output span:first-of-type {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"><span></span><span></span></div>
<textarea></textarea>
I guess you're using jQuery at least.
I created a fiddle for you http://jsfiddle.net/fdp1f715/ and a snippet :)
Is this what you want?
$(function () {
$('textarea#foo').on('keyup', function () {
var content = $(this).val();
var n = content.split(" ").length; // get number of words
$('p#nOfWords').text(n); // print number of words
$(this).removeClass('bar');
if (n > 50) {
$(this).addClass('bar');
}
});
});
textarea {
color: black;
}
textarea.bar {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<textarea id="foo"></textarea>
<p id="nOfWords"></p>
You could replace the contents with the contents having the first 50 words wrapped in a span. This means it has to be outside of an input field though. In any case, here's my stab at it (note that my demo limits to 3 words for demonstration purposes. Change {0,3} to {0,50} for 50):
$('textarea').on('input', function(){
$('.output').html(this.value.replace(/(([^\s]+\s*){0,3})(.*?)/, '<span>$1</span>$3'));
});
span {color:green}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="output"></div>
<textarea></textarea>
Yes you can do that. Here a vanilla javascript solution: http://jsfiddle.net/afhmpc4q/2/
<textarea id="area"></textarea>
JS
var checktext = {
"check": function () {
var words = this.value.match(/\S+/g).length;
if (words > 10) {
this.style.color = "red";
alert("over limit");
}
}
};
var areatocheck = document.getElementById("area");
areatocheck.onkeyup = checktext.check;

Increase size of input field as text is entered

I have a fairly simple CSS question. I have an input text field, and on page load i would like it to be 150px in width.
However, as the user enters some text, if the text is greater than 150px in width, then the width should auto adjust.
Here's a plunker:
http://plnkr.co/edit/ig0BQrJDiEtXKV8zJ2w2?p=preview
HTML:
<input class="input-class" type="text" placeholder="Placeholder">
CSS:
.input-class-2 {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
border-color: -moz-use-text-color -moz-use-text-color #ef8e80;
border-image: none;
border-style: none none dashed;
border-width: 0 0 1px;
color: #ef8e80;
cursor: pointer;
font-family: Gotham-Book;
font-size: 18px;
min-width: 150px;
}
I assumed min-width would do this.
There currently is no way to achieve this with pure CSS, perhaps once calc and attr can be used in combination, but not currently. So we have to fall back to JavaScript.
There isn't any real reason to use jQuery for this. You can argue that your "concerns should be separated" i.e. code should be separate from mark-up, but that is easy to do using addEventListener. However, if I'm dealing with one off small bits of JavaScript it tends to be faster — in terms of implementation, page render and even for those trying to track down what is making the input behave strangely — to use inline event listeners.
<input type="text"
style="min-width: 150px;"
onkeyup="this.size = Math.max(this.value.length, 1)"
/>
or:
<input type="text"
style="width: 150px;"
onkeyup="
this.style.width = '1px';
this.style.width = (
this.scrollWidth > 140
? this.scrollWidth + 10
: 150
)+'px';
"
/>
Disclaimer: Obviously if you are implementing many of these inputs it is far better to code a generalised function to handle them. Plus it is always far better to avoid inline style by using a stylesheet.
/**
* Directly setting the size attribute, with minWidth
*/
function autosize(elm, minWidth){
var keyup = function(e){
var t = e.target || e.srcElement;
var v = Math.max(t.value.length, 1);
t.setAttribute
? t.setAttribute('size', v)
: (t['size'] = v)
;
};
elm.style.minWidth = minWidth+'px';
elm.addEventListener
? elm.addEventListener('keyup', keyup)
: elm.attachEvent('onkeyup', keyup)
;
};
The size attribute is by far the most obvious choice, although you can directly set the width — if you prefer — using scrollWidth.
/**
* Directly setting width, with minWidth
*/
function autosize(elm, minWidth){
var keyup = function(e){
var t = e.target || e.srcElement;
t.style.width = '1px';
t.style.width = t.scrollWidth + 'px';
};
elm.style.minWidth = minWidth+'px';
elm.addEventListener
? elm.addEventListener('keyup', keyup)
: elm.attachEvent('onkeyup', keyup)
;
};
You can trigger either of these functions by passing your target element in as the first argument. There are a number of ways of finding your element, the easiest and most universal being getElementById. Although you will only be able to find your element if it has been parsed by the browser, so the script tag you use — to run the following code — will either have to be placed below the element in the mark-up i.e. bottom of <body> (preferable), or after waiting for window load, or DOM readiness.
autosize( document.getElementById('myinput'), 150 );
/**
* Directly setting width, with minWidth
*/
function autosize1(elm, minWidth){
var keyup = function(e){
var t = e.target || e.srcElement;
t.style.width = '1px';
t.style.width = t.scrollWidth + 'px';
};
elm.style.minWidth = minWidth+'px';
elm.addEventListener
? elm.addEventListener('keyup', keyup)
: elm.attachEvent('onkeyup', keyup)
;
};
/**
* Directly setting the size attribute, with minWidth
*/
function autosize2(elm, minWidth){
var keyup = function(e){
var t = e.target || e.srcElement;
var v = Math.max(t.value.length, 1);
t.setAttribute
? t.setAttribute('size', v)
: (t['size'] = v)
;
};
elm.style.minWidth = minWidth+'px';
elm.addEventListener
? elm.addEventListener('keyup', keyup)
: elm.attachEvent('onkeyup', keyup)
;
};
autosize1( document.getElementById('a'), 150 );
autosize2( document.getElementById('b'), 150 );
<p>Each input is using a different implementation:</p>
<input type="text"
style="min-width: 150px;"
onkeyup="this.size = Math.max(this.value.length, 1)"
/><br />
<input type="text"
style="width: 150px;"
onkeyup="
this.style.width = '1px';
this.style.width = (
this.scrollWidth > 140
? this.scrollWidth + 10
: 150
)+'px';
"
/><br />
<input type="text" id="a" /><br />
<input type="text" id="b" /><br />
You can try like this:
function resizeInput() {
$(this).attr('size', $(this).val().length);
}
$('input[type="text"]')
.keyup(resizeInput)
.each(resizeInput);
JSFIDDLE DEMO
There is one more alternative of using the
<span contenteditable="true">Some Text</span>
instead of using Input tags.
JSFIDDLE DEMO
You can try something like this
$('.input-class').keyup(function(){
var textlength=$('.input-class').val().length
$(this).width(textlength * 8)
})
.input-class{
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
border-color: -moz-use-text-color -moz-use-text-color #ef8e80;
border-image: none;
border-style: none none dashed;
border-width: 0 0 1px;
color: #ef8e80;
cursor: pointer;
font-family: Gotham-Book;
font-size: 18px;
min-width: 150px;
width:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input class="input-class" type="text" placeholder="Placeholder">
Tried to use pure JavaScript.
I hide a span element that's not shown (visibility:hidden;) to the user.
Then I calculate the span elements rendered width, and setting that to the container of the input.
And setting the input to be width:100%; makes it grow to the size of its parent.
var field = document.getElementById("grow");
field.oninput = function() {
var ruler = document.getElementById("ruler");
ruler.innerHTML = field.value.replace(/ /g," ");
var outer = document.getElementById("outer");
if (ruler.offsetWidth > 100) {
outer.setAttribute('style', "width:" + (ruler.offsetWidth + 5) + "px;");
} else {
outer.setAttribute('style', "");
}
};
#grow {
height: 100%;
width: 100%;
font-size: inherit;
font-family: inherit;
}
#outer {
width: 100px;
font-size: 1rem;
font-family: Serif, "Times New Roman", Georgia;
}
.hidden {
position: absolute;
display: inline;
visibility: hidden;
padding: 0;
font-size: inherit;
font-family: inherit;
white-space: nowrap;
}
<div id="outer">
<span id="ruler" class="hidden"></span>
<input id="grow" type="text/plain"/>
</div>
<p>+ Expands</p>
<p>+ shrinks</p>
<p>+ whitespace handling</p>

JQuery/JavaScript - highlight a part of text from input or textarea [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to highlight a part part of an Input text field in HTML using Javascript or JQuery
Does anyone know how to highlight some text in input[type=text] or textarea?
Is it possible?
You have to place a div behind your textarea and then style it according to it's text.
Notes:
Set your textarea background-color to transparent to see your highlighter color.
Your highlighter have to be the same style and text content of your textarea to put the span on the right place.
Set your highlighter text to the same color of it's background or you'll see a <b> effect, the same for the span.
html:
<div class="highlighter">some text <span>highlighted</span> some text</div>
<textarea>some text highlighted some text</textarea>
css:
.highlighter, textarea {
width: 400px;
height: 300px;
font-size: 10pt;
font-family: 'verdana';
}
.highlighter {
position: absolute;
padding: 1px;
margin-left: 1px;
color: white;
}
.highlighter span {
background: red;
color: red;
}
textarea {
position: relative;
background-color: transparent;
}
demo
This code snippet shows you how:
window.onload = function() {
var message = document.getElementById('message');
// Select a portion of text
createSelection(message, 0, 5);
// get the selected portion of text
var selectedText = message.value.substring(message.selectionStart, message.selectionEnd);
alert(selectedText);
};
function createSelection(field, start, end) {
if( field.createTextRange ) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
} else if( field.setSelectionRange ) {
field.setSelectionRange(start, end);
} else if( field.selectionStart ) {
field.selectionStart = start;
field.selectionEnd = end;
}
field.focus();
}

Categories