Resize TextArea on load - javascript

I'm having issues trying to resize a text area, I can do it as the user is typing but when they have submit it this gets put into a database and put into a text area below and display as a message on a message board but if the message exceeds the size of the Text Area it's not displayed I was wondering if anyone out there has had this issue and overcome it.
Here is the solution I came up with for the resizing whilst typing,
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);
This is called on keyup on the textarea in my other page where ive used it but I have tried to do something like this to resize when it loads but it doesn't work but it does work when a key is pressed or a button is clicked.
onload="resizeTextarea('commentstext');"
I know i could always have it scrollable or put it into a div but divs don't format the text like a textarea if i do a line break in the text and submit it to a div ti wont be there

See my modification of prior solution: http://jsfiddle.net/CbqFv/570/
HTML
<textarea cols="42" rows="1">
1 ...by default, you can write more rows</textarea><br />
<br />
<textarea cols="42" rows="5">
1
2
3
4
5 ...by default, you can write more rows</textarea><br />
<br />
<textarea cols="42" rows="10">
1
2
3
4
5
6
7
8
9
10 ...by default, you can write more rows</textarea>
CSS
textarea {
border: 1px solid gray;
border-radius: 3px;
line-height: 1.3em;
overflow: hidden;
padding: 0.3em 0.3em 0 0.3em;
outline: none;
background-color: white;
resize: none;
}
JavaScript
var observe;
if (window.attachEvent) {
observe = function (element, event, handler) {
element.attachEvent('on'+event, handler);
};
}
else {
observe = function (element, event, handler) {
element.addEventListener(event, handler, false);
};
}
function init () {
function resize (element) {
element.style.height = 'auto';
element.style.height = element.scrollHeight+'px';
}
/* 0-timeout to get the already changed text */
function delayedResize (element) {
window.setTimeout(function() { resize(element) }, 0);
}
var textareas = document.getElementsByTagName("textarea");
for (i = 0; i < textareas.length; i++) {
var textarea = textareas[i];
observe(textarea, 'change', function() { resize(this) });
observe(textarea, 'cut', function() { delayedResize(this) });
observe(textarea, 'paste', function() { delayedResize(this) });
observe(textarea, 'drop',function() { delayedResize(this) });
observe(textarea, 'keydown', function() { delayedResize(this) });
textarea.focus();
textarea.select();
resize(textarea);
}
}
init();

from autosize documentation:
Autosize has no way of knowing when the value of a textarea has been
changed through JavaScript. If you do this, trigger the
autosize.resize event immediately after to update the height. Example:
$('#example').val('New Text!').trigger('autosize.resize');
So after you update the textarea content, you'll have to call that trigger to autoresize it

Related

IE 10, 11. How to prevent the triggering of input events on focus from text input with placeholder?

In IE 11 if I have an empty email input with a placeholder, then on clicking (focusing) it, the input event is being triggered.
Does anyone know why and is there a solution to this, since the input value hasn't really changed?
var el = document.getElementById('myEmail');
el.addEventListener("input", myFunction, true);
function myFunction()
{
alert("changed");
}
<input id="myEmail" type="email" placeholder="Email">
I came very late to the party, but I had the same problem, and I came to a workaround to fix this behavior on IE.
In fact, there's two different bugs (or rather, only one bug but with two behavior depending on whether the target is an input or a textarea).
For input : the event is triggered each time the visual content of the field change, including keyboard inputting (naturally), but also when a placeholder appears/disappears (blur when no content), or when a visible placeholder is changed programmatically.
For textarea: it's basically the same, exepts that the event don't trigger when the placeholder disapears.
function onInputWraper(cb) {
if (!window.navigator.userAgent.match(/MSIE|Trident/)) return cb;
return function (e) {
var t = e.target,
active = (t == document.activeElement);
if (!active || (t.placeholder && t.composition_started !== true)) {
t.composition_started = active;
if ((!active && t.tagName == 'TEXTAREA') || t.tagName == 'INPUT') {
e.stopPropagation();
e.preventDefault();
return false;
}
}
cb(e);
};
}
var el = document.getElementById('myEmail');
el.addEventListener("input", onInputWraper(myFunction), true);
function myFunction() {
alert("changed");
}
<input id="myEmail" type="email" placeholder="Email">
And there's a full-working example, where you can also change placeholders value
function onInputWraper(cb) {
if (!window.navigator.userAgent.match(/MSIE|Trident/)) return cb;
return function (e) {
var t = e.target,
active = (t == document.activeElement);
if (!active || (t.placeholder && t.composition_started !== true)) {
t.composition_started = active;
if ((!active && t.tagName == 'TEXTAREA') || t.tagName == 'INPUT') {
e.stopPropagation();
e.preventDefault();
return false;
}
}
cb(e);
};
}
function handle(event) {
console.log('EVENT', event);
document.getElementById('output')
.insertAdjacentHTML('afterbegin', "<p>" + event.type + " triggered on " + event.target.tagName +
'</p>');
}
var input = document.getElementById('input'),
textarea = document.getElementById('textarea');
input.addEventListener('input', onInputWraper(handle));
textarea.addEventListener('input', onInputWraper(handle));
// input.addEventListener('input', handle);
// textarea.addEventListener('input', handle);
// Example's settings
function removeListeners(elem) {
var value = elem.value,
clone = elem.cloneNode(true);
elem.parentNode.replaceChild(clone, elem);
clone.value = value;
return clone;
}
document.querySelector('#settings input[type="checkbox"]').addEventListener('change', function (event) {
if (event.target.checked) {
document.getElementById('output').insertAdjacentHTML('afterbegin', '<p>Filter enabled !</p>');
//input = removeListeners(input);
console.log(input.value.length, (input == document.activeElement));
input = removeListeners(input);
input.addEventListener('input', onInputWraper(handle));
input.composing = input.value.length > 0 || (input == document.activeElement);
textarea = removeListeners(textarea);
textarea.addEventListener('input', onInputWraper(handle));
textarea.composing = textarea.value.length > 0 || (textarea == document.activeElement);
} else {
document.getElementById('output').insertAdjacentHTML('afterbegin', '<p>Filter disabled !</p>');
input = removeListeners(input);
input.addEventListener('input', handle);
input.composing = void 0;
textarea = removeListeners(textarea);
textarea.addEventListener('input', handle);
textarea.composing = void 0;
}
});
document.getElementById('input_cfg').addEventListener('click', function () {
document.getElementById('input').setAttribute('placeholder', document.getElementById(
'input_placeholder').value);
});
document.getElementById('textarea_cfg').addEventListener('click', function () {
document.getElementById('textarea').setAttribute('placeholder', document.getElementById(
'textarea_placeholder').value);
});
* {
font: 15px arial, sans-serif;
}
dd {
background: FloralWhite;
margin: 0;
}
dt {
padding: 15px;
font-size: 1.2em;
background: steelblue;
color: AntiqueWhite;
}
p {
margin: 0;
}
button,
label {
width: 300px;
margin: 5px;
padding: 5px;
float: left;
color: DarkSlateGray;
}
#settings label {
width: 100%;
margin: 15px;
}
#forms input,
#forms textarea,
#settings input:not([type]) {
display: block;
width: calc(100% - 340px);
padding: 7px;
margin: 0;
margin-left: 320px;
min-height: 25px;
border: 1px solid gray;
background: white;
cursor: text;
}
::placeholder {
/* Chrome, Firefox, Opera, Safari 10.1+ */
color: LightBlue;
opacity: 1;
/* Firefox */
}
::-ms-input-placeholder {
/* Microsoft Edge */
color: LightBlue;
}
:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: LightBlue;
}
<dl>
<dt>Forms</dt>
<dd id="forms">
<label for="input">Input: </label>
<input id="input" name="input" class="testing" placeholder="Type some text" />
<label for="texarea">Textarea: </label>
<textarea id="textarea" name="textarea" placeholder="Type some text"></textarea>
</dd>
<dt>Settings</dt>
<dd id="settings">
<p>
<label><input type="checkbox" checked>Enable filtering script</label>
<button id="input_cfg">Change input's placeholder to</button><input id="input_placeholder" />
</p>
<p>
<button id="textarea_cfg">Change textarea's placeholder to</button>
<input id="textarea_placeholder" />
</p>
</dd>
<dt>Output</dt>
<dd id="output"></dd>
</dl>
or on jsfiddle
It seems like a bug. oninput has been supported since IE9 should only fire when the value is changed. An alternate approach would be to use onkeyup
https://developer.mozilla.org/en-US/docs/Web/Events/input
If you want to handle input and validation you can just add a second eventlistener (assuming your html is the same as above).
var el = document.getElementById('myEmail');
function myFunction() {
console.log("changed");
}
el.addEventListener("keyup", myFunction, true);
function validation() {
console.log("validated");
}
el.addEventListener("keyup", validation, true);
The solution is very short!
At first we don't need so much of code what we can see in accepted answer. At second you have to understand why it is happening:
Fake oninput event triggers only on inputs with a placeholder on getting a focus and only if the input value is empty. It happens because bad developer from IE had thought that the input value changes from placeholder value to real value, but it is misunderstanding from this bad developer from IE.
An input without placeholders doesn't have this problems.
The first solution is very simple: do not use a placeholder if you do not really need it. In most cases you can add a title to the element instead of a placeholder. You could also write your placeholder text before, below or above the input.
If you have to use a placeholder
The second solution is also very simple and short: save the previous value on the input object and compare it with a new value – if it was not changed then return from the function before your code.
Life examples
var input = document.querySelector('input[type=search]');
input.addEventListener('input', function(e)
{
if(this.prevVal == this.value /* if the value was not changed */
|| !this.prevVal && '' == this.value) //only for the first time because we do not know the previous value
return; //the function returns "undefined" as value in this case
this.prevVal = this.value;
//YOUR CODE PLACE
console.log('log: ' + this.value)
}, false);
<input type="search" placeholder="Search..."/>
Or if you use it as inline JavaScript:
function onSearch(trg)
{
if(trg.prevVal == trg.value /* if the value was not changed */
|| !trg.prevVal && '' == trg.value) //only for the first time because we do not know the previous value
return; //the function returns "undefined" as value in this case
trg.prevVal = trg.value; // save the previous value on input object
//YOUR CODE PLACE
console.log('log: ' + trg.value);
}
<input type="search" placeholder="Search..." oninput="onSearch(this)"/>

Change dynamically number of rows on submit

I need your help guys.
I use a textarea that automatically expands by changing the number of rows.
In my project, the page does not reload and stays as it is after submitting the form. I need to change dynamically the number of rows (2) on submit.
Also one can send the form by Enter. So I need to change the number of rows after pushing a button or hitting the Enter key.
I've coded a rough sketch of the form that I have in my project so that you could test it: https://codepen.io/C3La-NS/pen/NagZbr
<form id="NewMessage">
<textarea id="shoutbox-comment" data-min-rows="2"></textarea>
<button id="send_message" type="submit" onclick="chatSubmit();">send</button>
</form>
JS:
// auto-resizing textarea
const textarea = document.getElementById("shoutbox-comment");
textarea.addEventListener("input", function() {
this.rows = 2; // Erm...
this.rows = countRows(this.scrollHeight);
});
function countRows(scrollHeight) {
return Math.floor(scrollHeight / 20); // 20px = line-height: 1.25rem
}
// submit by Enter
$(document).ready(function() {
$("#shoutbox-comment").on("keypress", function(event) {
if (event.keyCode == 10 || event.keyCode == 13) {
event.preventDefault();
chatSubmit();
}
});
});
// submit FORM
function chatSubmit() {
$("#NewMessage").submit();
}
Thank you!
jQuery submit accept as parameter a callback that is triggered before submit so, you can do:
$("#NewMessage").submit(function( event ) {
event.preventDefault();
$('#shoutbox-comment').attr('rows', 2);
});
Just couple of changes in your script:
const textarea = $("#shoutbox-comment");
const minRows = textarea.data('minRows');
textarea.on("input", function(e) {
this.rows = 1; // Erm...
this.rows = countRows(this.scrollHeight);
});
function countRows(scrollHeight) {
var toReturn = Math.floor(scrollHeight / 20); // 20px = line-height: 1.25rem
return toReturn > minRows ? toReturn : minRows;
}
// submit by Enter
$(document).ready(function() {
$("#shoutbox-comment").on("input", function(e) {
if (e.keyCode == 10 || e.keyCode == 13) {
e.preventDefault();
chatSubmit();
}
});
});
// submit FORM
function chatSubmit() {
// Send the message via AJAX;
textarea.val('').trigger('input');
return false;
}
#shoutbox-comment {
width: 220px;
outline: none;
resize: none;
line-height: 20px;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="NewMessage">
<textarea id="shoutbox-comment" data-min-rows="2"></textarea>
<button id="send_message" type="submit" onclick="chatSubmit();">send</button>
</form>
I've also included data-min-rows attribute inside the script.
Also on CodePen.

Javascript -- how to click anywhere on page to hide opened div

I have a javascript that opens up a hidden div:
<script>
function dropdown()
{ document.getElementById("login_dropdown").style.display="block"; }
</script>
The html is:
<div onclick="dropdown()">
<div id="login_dropdown">STUFF</div>
</div>
The CSS is:
<style>
#login_dropdown {
width: 150px;
display:none;
}</style>
Using javascript alone, how can I hide this div when I click anywhere else on the page, excluding the opened DIV itself.
Something like this with vanilljs
document.addEventListener('click', function(event){
const yourContainer = document.querySelector('....');
if(!yourContainer.contains(event.target)) {
//hide things classes.. yourContainer.classList.add('hidden');
}
});
You could do this
var elem = document.getElementById("login_dropdown");
(document.body || document.documentElement).addEventListener('click', function (event) {
// If the element on which the click event occurs is not the dropdown, then hide it
if (event.target !== elem)
elem.style.display="none";
}, false);
function closest(e, t){
return !e? false : e === t ? true : closest(e.parentNode, t);
}
container = document.getElementById("popup");
open = document.getElementById("open");
open.addEventListener("click", function(e) {
container.style.display = "block";
open.disabled = true;
e.stopPropagation();
});
document.body.addEventListener("click", function(e) {
if (!closest(e.target, container)) {
container.style.display = "none";
open.disabled = false;
}
});
#popup {
border: 1px solid #ccc;
padding: 5px;
display: none;
width: 200px;
}
<div id="container">
<button id="open">open</button>
<div id="popup">PopUp</div>
</div>
Something like this:
$("document").mouseup(function(e)
{
var subject = $("#login_dropdown");
if(e.target.id != subject.attr('id'))
{
subject.css('display', 'none');
}
});
works like this. When you click anywhere on the page, the handler fires and compares the ID of the open tab vs the id of the document (which there is none) - so it closes the tab. However, if you click the tab, the handler fires, checks the ID, sees the target is the same and fails the test (thus not closing the tab).

click event on re-appended child in dom

I'm trying to catch a click event on an element which changes its z-pos using appendchild on the mousedown event. The problem is that when you click an element when its not the front element then the click event doesn't fire. I know this is because it is removed from the DOM and then re-added but I'm not sure how I could fix it so that the click also fire when the element is moved to the front.
MyObject = {
init(parent, text) {
this.parent = parent;
this.text= text;
this.visual = document.createElement("div");
this.visual.setAttribute("class", "object");
this.visual.appendChild(document.createTextNode(text))
parent.appendChild(this.visual);;
this.visual.addEventListener("click", (e) => { this.onClicked(e); });
this.visual.addEventListener("mousedown", (e) => { this.onMouseDown (e); });
},
toTop() {
this.parent.appendChild(this.visual);
},
onClicked(e) {
alert(this.text + " was clicked");
e.stopPropagation();
},
onMouseDown(e) {
this.toTop();
// I'm also doing other things here
}
};
var parent = document.querySelector(".parent");
parent.addEventListener("click", (e) => { alert("parent clicked"); });
var createObj = function(text) {
var obj = Object.create(MyObject);
obj.init (parent, text);
};
createObj ("object 1");
createObj ("object 2");
createObj ("object 3");
createObj ("object 4");
.parent {
border: 1px solid red;
}
.object {
background: #0F0;
border: 1px solid black;
margin: 8px;
}
<div class="parent">
</div>
So in this example you always have to click the bottom element to get the alert while I would also like to get the alert when an other items is pressed.
edit: I'm testing in chrome (55.0.2883.87) and the code might not work in other browsers.

show search field when some starts typing on the web page

When someone starts typing (number or alphabets), I want a search bar to appear and it should take the alphabets that are being written by the user in it, ie, I want it to automatically focus on the field.
So far I have this..
if (window.addEventListener) {
var keys = [], listen= /^([0-9]|[a-z])\i$/ ;
window.addEventListener("keydown", function(e){
keys.push(e.keyCode);
if(keys.match(listen))
{
$('#searchBar').fadeIn();
$('#searchBar input').text(keys);
$('#searchBar input').focus();
keys = [];
}
},true);
}
I want the first character that was typed in to show in the field too.
Ty.
Hope this works for you. If you prefer jQuery, minor changes needs to be made.
<style>
#searchBar { display: none; }
.search { width: 250px; height: 20px; }
</style>
<div id="searchBar">
Search Here: <input type="search" id="searchInput" class="search" />
</div>
<script>
window.onload = function() {
var listen = /^[a-z0-9]+$/i;
var searchInput = document.getElementById('searchInput');
var searchBar = document.getElementById('searchBar');
if ( window.addEventListener )
window.addEventListener( 'keyup', insertKey, false);
function insertKey( e ) {
// Get the character from e.keyCode
var key = String.fromCharCode( e.keyCode ).toLowerCase();
// Match the character
if( key.match(listen) ) {
// Change display: none; to display: block;
searchBar.style.display = "block";
// Append every new character
searchInput.value += key;
// Focus on input
searchInput.focus();
// Since you focused on the input you don't need to listen for keyup anymore.
window.removeEventListener( 'keyup', insertKey );
// I didn't tested with jQuery
// $('#searchBar').fadeIn();
// $('#searchBar input').append(keys);
// $('#searchBar input').focus();
}
}
};
</script>
var listen= /^([0-9]|[a-z])\i$/;
var key = [];
window.addEventListener('keydown', function (e) {
keys.push(e.keyCode);
if(keys.match(listen)) {
$('#searchBar').fadeIn();
$('#searchBar input').append(keys);
$('#searchBar input').focus();
keys = [];
}
});

Categories