HTML TextArea resize automatically - javascript

I would like to have a text area which is always as big as the text in it. So the page can be scrolled and in the text area cannot be scrolled.
Here's what I did until now:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html, body {height: 100%;}
textarea {
border: none;
width: 100%;
height: 100%;
-webkit-box-sizing: border-box;
line-height: 44px;
font-family:Helvetica;
font-size: 17pt;
-webkit-tap-highlight-color: rgba(0,0,0,0);
background-image:url('linedBack#2x.png');
outline: none;
resize: none;
}
textarea.vert { resize:vertical; }
</style></head><body>
<textarea id="InputTextArea" placeholder="placeholder"></textarea>
</body></html>

Resizing TeaxArea based on the content line number. Here's a DEMO
JS
function resizeTextarea (id) {
var a = document.getElementById(id);
a.style.height = 'auto';
a.style.height = a.scrollHeight+'px';
}
function init() {
var a = document.getElementsByTagName('textarea');
for(var i=0,inb=a.length;i<inb;i++) {
if(a[i].getAttribute('data-resizable')=='true')
resizeTextarea(a[i].id);
}
}
addEventListener('DOMContentLoaded', init);
HTML
<textarea id="InputTextArea" placeholder="placeholder" onkeyup="resizeTextarea('InputTextArea')"></textarea>

If you are using AngularJS, you can do :
<textarea ng-keyup="ctl.handleTextAreaHeight($event)"></textarea>
With this in your controller :
this.handleTextAreaHeight = function (e) {
var element = e.target;
element.style.overflow = 'hidden';
element.style.height = 0;
element.style.height = element.scrollHeight + 'px';
};

In case anyone still needs this, for what it's worth, here's mine in pure js. But first, you may check this one:
Auto expand a textarea using jQuery
var textAreas = document.getElementsByTagName('textarea');
try {
taLength = textAreas.length;
for (i=0; i < taLength; i++) {
var taId = textAreas[i].id;
document.getElementById(taId).addEventListener('input', function(e) {
e.target.style.height = "auto";
//This makes your textarea back to its original size. So you can replace it with any size you want it to have e.g. "120px"
//You may need some logic if you have multiple taxtareas with different original sizes
e.target.style.height = e.target.scrollHeight+'px';
});
}
}
catch (err) {
window.alert(err);
}
I used shubhra's answer to build that one. It is smooth and the scrollbar won't appear.

If someone need a solution for Vue.js. Here is a vue directive to do a auto resizing text area. Just register directive globally once and you can use it for any textarea
Vue.directive('resizable', {
inserted: function (el) {
el.addEventListener('input', function(e) {
e.target.style.height = "auto";
e.target.style.height = e.target.scrollHeight + 'px';
});
}
});
html is easy, just put v-resizable attribute in textarea
<textarea v-resizable></textarea>
Special thanks to AniMir! I am using his input event handler.

Just setting height = scrollHeight misses the goal when box-sizing: border-box is set. Here is a solution with a fix for that and which allows the textarea to shrink again.
// auto resize the textareas
document.querySelectorAll("textarea").forEach(function (el) {
el.addEventListener("input", function () {
var cs = window.getComputedStyle(this);
// reset height to allow textarea to shrink again
this.style.height = "auto";
// when "box-sizing: border-box" we need to add vertical border size to scrollHeight
this.style.height = (this.scrollHeight + parseInt(cs.getPropertyValue("border-top-width")) + parseInt(cs.getPropertyValue("border-bottom-width"))) + "px";
});
});
// compat window.getComputedStyle: IE9
// compat NodeList.forEach: No IE (but not necessary here)
* { box-sizing: border-box; }
textarea { width: 20%; }
#a { padding: 1em; }
#b { padding: 0; }
#c { max-height: 7em; }
#d {
border-top: 10px solid blue;
border-bottom: 10px solid blue;
}
<textarea id="a">1em padding</textarea>
<textarea id="b">0 padding</textarea>
<textarea id="c">max-height: 7em</textarea>
<textarea id="d">10px vertical borders</textarea>

<textarea
id="newComm"
class="form-control"
name="comment"
placeholder="Some text"
cols="30"
:rows="rowsHeight"
wrap="soft"
v-model.trim="newCommText"
#input="changeRows"
:style="'resize: none; overflow: hidden; line-height: '+lineHeight+'px;'"
></textarea>
setup() {
const newCommText = ref(null)
const rowsHeightStart = ref(5)
const rowsHeight = ref(rowsHeightStart.value)
const lineHeight = ref(25)
function changeRows (event) {
rowsHeight.value = event.target.value.split("\n").length > rowsHeightStart.value ? event.target.value.split("\n").length : rowsHeightStart.value
}
return {
rowsHeight, lineHeight, newCommText,
changeRows
}

Related

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>

Is there a way to check the bottom of a child div?

I'm trying to implement an Infinity scroll.
But not a window object, the target is a child div with a scroller.
Is there a way to examine the current height of a child div with JavaScript?
For example, I would like to request an event when the scroll touches at the end.
This is my template code.
<div
style="overflow-y: scroll; height:500px;"
class="scroll-content"
#scroll="onScroll"
>
Here is an example:
var listElm = document.querySelector('#infinite-list');
// Add items.
var nextItem = 1;
var loadMore = function() {
for (var i = 0; i < 10; i++) {
var item = document.createElement('li');
item.innerText = 'Item ' + nextItem++;
listElm.appendChild(item);
}
}
// Detect when scrolled to bottom.
listElm.addEventListener('scroll', function() {
if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
loadMore();
}
});
// Initially load some items.
loadMore();
#infinite-list {
/* We need to limit the height and show a scrollbar */
width: 200px;
height: 100px;
overflow: auto;
/* Optional, only to check that it works with margin/padding */
margin: 30px;
padding: 20px;
border: 10px solid black;
}
/* Optional eye candy below: */
li {
padding: 10px;
list-style-type: none;
}
li:hover {
background: #ccc;
}
<ul id='infinite-list'>
</ul>
The following function returns, whether the user has scrolled to the bottom of a certain element:
function scrollEnd(el) {
return (el.scrollTop + el.offsetHeight >= el.scrollHeight);
}
If you add this to a scroll event listener:
element.addEventListener('scroll', () => {
if (scrollEnd(element)) {
// the user reached the end
}
})
I tried this on a textarea, should work with anything, though.

Make DOM elements equal by height

I write JavaScript/TypeScript function:
function setElementsHeightsEqual(el1: HTMLElement, el2: HTMLElement) {
...
}
This is typical situation when you want to attach some button (el2) to some input (el1) dynamically.
I want to make el2's height equal to el1, but I am unable to do it.
There are two problems:
All possible calls returning height are helpless for me:
el1.offsetWidth; // will return 0 if document is not rendered yet
el1.style.height; // will return "" if it is set inside external CSS
el1.style.paddingTop; // the same
el1.style.paddingBottom; // the same
In other words is there any possibility to calculate height of some specified element?
How to set height of el2? We do not know even its "box-sizing", the same problem as in (1).
Are these tasks impossible in JS + HTML DOM?
offsetHeight is a safe way to go. If the element is not loaded, move your function call to window.onload.
Here you have a working example:
function setMaxHeight(...elements) {
console.log(elements);
// Get max height
var height = 0;
for(let element of elements) {
console.log(element.offsetHeight);
if(element.offsetHeight > height) height = element.offsetHeight;
}
// Change all elements height to max.
for(let element of elements) {
element.style.height = height + 'px';
}
}
window.onload = function() {
var object1 = document.querySelector('.object1');
var object2 = document.querySelector('.object2');
var object3 = document.querySelector('.object3');
setMaxHeight(object1, object2, object3);
};
.object1 {
border: 1px solid #000;
display: block;
float: left;
height: 50px;
width: 20%;
}
.object2 {
border: 1px solid #0cc;
display: block;
float: left;
height: 120px;
width: 30%;
}
.object3 {
border: 1px solid #afc;
display: block;
float: left;
height: 20px;
width: 10%;
}
<div id="container">
<div class="object1">Text</div>
<div class="object2">Text2</div>
<div class="object3">Text3</div>
</div>
Compare running with and without the Javascript portion.
I hope this helps.
It is the way I set the equal height to elements I want.
Give a class name to your elements which you want to make their height the same.
<div class="sameElementHeight">
<img src="/path/to/Image" class="sameImageHeight">
<p>YOUR TEXT</p>
</div>
<div class="sameElementHeight">
<img src="/path/to/Image" class="sameImageHeight">
<p>YOUR TEXT</p>
</div>
<div class="sameElementHeight">
<img src="/path/to/Image" class="sameImageHeight">
<p>YOUR TEXT</p>
</div>
First, create a function like this:
equalheight = function(container){
var currentTallest = 0,
currentRowStart = 0,
rowDivs = new Array(),
$el,
topPosition = 0;
jQuery(container).each(function() {
$el = jQuery(this);
jQuery($el).height('auto')
topPostion = $el.position().top;
if (currentRowStart != topPostion) {
for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
rowDivs.length = 0; // empty the array
currentRowStart = topPostion;
currentTallest = $el.height();
rowDivs.push($el);
} else {
rowDivs.push($el);
currentTallest = (currentTallest < $el.height()) ? ($el.height()) : (currentTallest);
}
for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
});
}
Then call it before closing body tag:
<script>
equalheight(".sameElementHeight");
equalheight(".sameImageHeight");
</script>
</body>
You also may call this function when you add new elements to your document.
It will calculate the height of the element and set the same height to them and also does the same with images.
I hope it helps.

Making a javascript popup draggable

I am creating a JavaScript popup. The code is as below.
The HTML:
<div id="ac-wrapper" style='display:none' onClick="hideNow(event)">
<div id="popup">
<center>
<h2>Popup Content Here</h2>
<input type="submit" name="submit" value="Submit" onClick="PopUp('hide')" />
</center>
</div>
</div>
The CSS:
#ac-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url("images/pop-bg.png") repeat top left transparent;
z-index: 1001;
}
#popup {
background: none repeat scroll 0 0 #FFFFFF;
border-radius: 18px;
-moz-border-radius: 18px;
-webkit-border-radius: 18px;
height: 361px;
margin: 5% auto;
position: relative;
width: 597px;
}
The Script:
function PopUp(hideOrshow) {
if (hideOrshow == 'hide') document.getElementById('ac-wrapper').style.display = "none";
else document.getElementById('ac-wrapper').removeAttribute('style');
}
window.onload = function () {
setTimeout(function () {
PopUp('show');
}, 0);
}
function hideNow(e) {
if (e.target.id == 'ac-wrapper') document.getElementById('ac-wrapper').style.display = 'none';
}
The jsFiddle Link:
http://jsfiddle.net/K9qL4/2/
The Issue:
The above script works fine, but I need to make the popUp draggable.
Here's some code that will do what you want. It relies only on an object called drag to store all its values, but you can easily alter that. The example relies on there being a div with the id of mydiv (a document.write() is used in this instance to supply that) that has a position attribute of absolute or fixed. You can see it in action at Jamie
document.write("<" + "div id='mydiv' style='background:blue; width:100px;"
"height:100px; position:fixed;'>" + "<" + "/div>");
var drag = new Object();
drag.obj = document.getElementById('mydiv');
drag.obj.addEventListener('mousedown', function(e)
{
drag.top = parseInt(drag.obj.offsetTop);
drag.left = parseInt(drag.obj.offsetLeft);
drag.oldx = drag.x;
drag.oldy = drag.y;
drag.drag = true;
});
window.addEventListener('mouseup', function()
{
drag.drag = false;
});
window.addEventListener('mousemove', function(e)
{
drag.x = e.clientX;
drag.y = e.clientY;
var diffw = drag.x - drag.oldx;
var diffh = drag.y - drag.oldy;
if (drag.drag)
{
drag.obj.style.left = drag.left + diffw + 'px';
drag.obj.style.top = drag.top + diffh + 'px';
e.preventDefault();
}
});
Use the
.draggable();
jquery function, here is your updated fiddle:
http://jsfiddle.net/N9rQK/
If you don't want to use jQuery, you should read this subject: Draggable div without jQuery UI

javascript chatbox / messenger script

I'm trying to write a facebook like chatbox, but i've encountered a small problem.
I'm using the following code (it's only test code, so it's not really clean):
css code:
#messenger {
position: fixed;
bottom: 0px;
right: 10px;
width: 200px;
height: 300px;
z-index: 4;
background-color: #ECECEC;
border: 1px solid #000;
}
#messenger.p {
text-align: right;
}
#contacts {
margin: 5px 5px 5px 5px;
}
#chatspace {
position: fixed;
bottom: 0px;
right: 240px;
height: 20px;
left: 20px;
background-color: #ECECEC;
border: 1px solid #000;
z-index: 4;
}
.chatbox {
position: absolute;
bottom: 0px;
width: 200px;
height: 200px;
z-index: 4;
background-color: #ECECEC;
border: 1px solid #000;
}
html/javascript code:
<script type="text/javascript">
var i = 0;
function oc_chatbox() {
if (i == 0) {
document.getElementById('contacts').style.visibility = 'hidden';
document.getElementById('messenger').style.height = '20px';
i = 1;
}
else {
document.getElementById('contacts').style.visibility = 'visible';
document.getElementById('messenger').style.height = '300px';
i = 0;
}
}
function new_chat(userid) {
var new_right;
new_right = document.getElementById('messenger').style.right;
//alert('old value: '+ new_right);
new_right += 20;
//alert('New value of right: '+ new_right);
document.getElementById('chatspace').innerHTML = '<div id="'+userid+'" class="chatbox" style="right: '+new_right+'px;"></div>';
//document.write('<div id="'+userid+'" class="chatbox" style="right: '+new_right+'px;"></div>');
}
</script>
<div id="chatspace"></div>
<div id="messenger">
<p>Collapse</p>
<div id="contacts">
<ul>
<li>contact A</li>
</ul>
</div>
</div>
the problem is, that when I try to add new chats to the chatbar, i can't seem the place them next to each other.
anyone who can help ?
EDIT:
so i changed to javascript code to:
var last = null;
function new_chat(userid) {
if(userid==null)
userid = "user666";
var new_right;
var margin = 10;
var messenger = window.last==null?document.getElementById('messenger'):window.last; //Take the messenger or the last added chat
new_right = document.body.clientWidth-messenger.offsetLeft; //Compute the window size
console.log(new_right); //Log the number
new_right += margin; //keep spaces between divs
var newChat = document.createElement("div"); //DOM create DIV
newChat.id = userid;
newChat.className = "chatbox shadow";
newChat.style.right = new_right+"px";
newChat.innerHTML = '<p>'+userid+'</p><p><textarea></textarea></p>';
window.last = newChat; //Remember whichever is last
document.body.appendChild(newChat);
}
and now it works, thanks !
You cannot get an element right offset using its style, unlest the style is set and valid. Instead you must get element.offsetLeft and size of window area and do this:
new_right = windowSize()[0]-messenger.offsetLeft;
Where window size is this function.
Here is my, working, version of your function:
var last = null;
function new_chat(userid) {
if(userid==null)
userid = "user666";
var new_right;
var margin = 20;
var messenger = window.last==null?document.getElementById('messenger'):window.last; //Take the messenger or the last added chat
new_right = windowSize()[0]-messenger.offsetLeft; //Compute the window size
console.log(new_right); //Log the number
new_right += margin; //keep spaces between divs
var newChat = document.createElement("div"); //DOM create DIV
newChat.id = userid;
newChat.className = "chatbox";
newChat.style.right = new_right+"px";
window.last = newChat; //Remember whichever is last
document.body.appendChild(newChat);
}
You may get errors if console is not defined in your brouwser. But in such case you should take a better browser. Normally, the if(console!=null) is put in code.
And here is the link.
You should try adding a float style.
.chatbox {
float: right;
}
Add that to your chatbox styles. You may need to mess around a bit to make sure the float doesn't mess with your other elements. You may need a better container for them.
If you want to get really fun, you can add .draggable() from jQuery, and you can have them snap to your chat bar. You can then change the order of your chats.

Categories