jQuery: making a textarea slide out when rows are changed? - javascript

I have a text area box that expands from 3 to 17 rows when the user enters so many characters as well as on a button click.
SetNewSize(); function is the called via onkeyup and expands the text area when the length becomes greater than 50.
morespace(); function is called via the button.
I would like to slide the box out when this happens, any ideas?
Thanks here is my code:
function SetNewSize(textarea){
if (textarea.value.length > 50)
{
textarea.rows = 17;
}
else
{
textarea.rows = 3;
}}
function morespace(){
var thetxt = document.getElementById('more').value;
var box = document.forms["myForm"]["comment"];
if(box.rows == 3)
{
$("#emailme").fadeOut(800);
box.rows = 17;
document.getElementById('more').innerHTML = "less space?";
}
else
{
$("#emailme").fadeIn(800);
box.rows = 3;
document.getElementById('more').innerHTML = "more space?";
}}

By "slide the box out", I'm guessing you mean animate it. While you may not be able to animate textarea rows in jQuery, you can animate the height of the textarea to give the user more room. For example, you trigger something like this:
$('#comment').animate({'height': '+=40'},200);
This will add 40 pixels of height every time it is triggered and it animates it smoothly. If you want to add a number rows, you could simply calculate how large you want the textarea to become and then animate it to that height.
Here's a JSFiddle link for this action and you may want to check out the jQuery animate API.

Well, the quick answer is use something someone already made: https://github.com/gurglet/jQuery-Textarea-Autoresize-Plugin
But if you want to roll your own, I'll update my reply in a moment with the code you need.
Updated Answer:
Assuming you have this HTML:
<button id="emailme">Email me</button>
<form id="myForm">
<input id="more" name="more" type="text">
<textarea id="comment" name="comment" rows="3">
</textarea>
</form>
You could then use this script:
(function(){
var BIG = 17,
SMALL = 3,
currentSize = SMALL,
changeSize = function(rows) {
var $more = $("#more"),
thetxt = $more.val(),
$box = $("#comment"),
currentRows = $box.prop("rows"),
boxRowHeight = $box.height()/currentRows,
newHeight = rows * boxRowHeight;
if (rows === currentRows) return;
return $box.animate({'height': newHeight }, 500 , "swing", function(){
$more.val((currentRows > rows) ? "more space?" : "less space?");
$box.prop("rows", rows);
currentSize = rows;
}).promise();
},
setNewSize = function(event) {
var $area = $(event.target);
if ($area.val().length > 50 && currentSize === SMALL) {
changeSize(BIG);
currentSize = BIG ;
}
};
$("#comment").bind("keyup", setNewSize);
$("#more").click(function(){
if (currentSize === BIG) {
$.when(changeSize(SMALL)).then(function(){
$("#emailme").fadeIn(800);
});
}else{
$.when(changeSize(BIG)).then(function(){
$("#emailme").fadeOut(800);
});
}
});
}​)();​
JSFiddle Link: http://jsfiddle.net/isochronous/fvtY7/

You could also use jquery's attr() like so:
$('#comment').attr('rows', 17);
Where rows represent the attribute to cahnge and 17 the value to set.
To get the number of rows currently used you use:
var rows = $('#comment').attr('rows');

Related

Wrap a row of blocks in the middle instead of end (CSS/JS/jQ)

How can a row of inline-blocks be wrapped by a shrinking parent resulting in equal (or almost equal) rows?
So instead of wrapping like this:
wrap like this:
And if there's an uneven number of blocks, like this:
You can use CSS Grid grid-template-columns and #media (if you want to wrap by screen-width) or in JS with docment.getElementById('bottomblocks').style.gridTemplateColumns variable to achieve this. (If I understand correctly)
I wrote here an example with JS:
https://jsfiddle.net/Lhbqdt2z/
You can learn about it where I started with it: Coding Tech Talk
Or just from W3Schools
Moz://a has a good examples here
He is something fun I just wrote... Assuming you want an "enhanced wrap" behavior that wraps by the half of its childs, instead of the normal floating.
It's more an "essay" than a strong best practice answer. ;)
$(window).on("load resize",function(){
$(".container div").css({"clear":"initial"});
var wrapped = false;
var wrappedAt = 0;
var wrappedNtimes =0;
var pos = $(".container div").first().offset();
var n = $(".container div").length;
$(".container div").each(function(index){
if(!wrapped){
if( ($(this).offset().top != pos.top)){
console.log("Wrapped at "+index+" out of "+n);
wrapped = true;
wrappedAt = index;
wrappedNtimes++;
}
pos=$(this).offset();
}
});
if(wrapped){
// Force enhanced wrapping... .oO(lol)
console.log("--"+wrappedAt+"--");
var half = Math.ceil(n/(wrappedNtimes+1));
$(".container div").each(function(){
if( $(this).index() != 0 && ($(this).index())%half == 0){
$(this).css({"clear":"left"}); // zero-based.
}
});
}
});
CodePen demo
Here's a solution that inserts <br> elements at the ends of each row. This code can be placed into a function to run whenever you need to wrap the blocks.
// Make sure that the last row of blocks doesn't have 2 less blocks than all
// the previous rows. Assume that all blocks are equal size.
var blocks = sharing.find('.btn');
//what's the parent width
var parentWidth = blocks.parent().width();
//how many blocks can fit in such a width
var maxNumOfBlocksInOneRow = Math.floor(parentWidth / blocks.outerWidth(true));
//repeatable code
var calcNumOfBlocksInLastRow = function(){
var lastRowFull = blocks.length % maxNumOfBlocksInOneRow ? false : true;
if (lastRowFull) {
return maxNumOfBlocksInOneRow;
} else {
return blocks.length % maxNumOfBlocksInOneRow;
}
}
//do we have more blocks than row's maximum?
if (blocks.length > maxNumOfBlocksInOneRow) {
//how many blocks would the last row have
var numOfBlocksInLastRow = calcNumOfBlocksInLastRow();
//if the last row is missing more than 1 block, try with 1 less block in each row
while (numOfBlocksInLastRow < maxNumOfBlocksInOneRow - 1) {
maxNumOfBlocksInOneRow--;
numOfBlocksInLastRow = calcNumOfBlocksInLastRow();
}
//insert <br> at the end of each row
jQuery('<br>').insertAfter(blocks.filter(':nth-child(' + maxNumOfBlocksInOneRow + 'n)'));
}

CSS/JS - Can you treat browser auto line breaks like rows to color them?

I am not quite sure how to put my Question in the right words, but I try to describe what I want to do.
Let's say we have a set of data (eg. numbers) from a database and they need to be output as a list. I put a predefined amount of data-fields in a row (for dekstop systems). Every data is in a SPAN with color/margin/padding styles. (Like table-cells.) After that amount of Spans is reached, a forced line break is given. And with each line break, the background color for all spans in that "row" is altered (odd/even). So far no problem.
However, if now someone checks that page with a Smartphone (or you simple resize your Browser Window), the predefined amount does not fit anmyore. As example, in large resolutions you have 6 Spans side by side, colored odd, than 6 Spans colored even. In a small resolution you maybe only have 3 Spans side by side, however in my design you have still 6 Spans colored odd, so two "rows" with the same background-color before it is altered.
Example HTML Output:
<span class="odd">Number 01</span>
<span class="odd">Number 02</span>
<span class="odd">Number 03</span>
<span class="odd">Number 04</span>
<span class="odd">Number 05</span>
<span class="odd">Number 06</span>
<br/>
<span class="even">Number 07</span>
<span class="even">Number 08</span>
<span class="even">Number 09</span>
<span class="even">Number 10</span>
<span class="even">Number 11</span>
<span class="even">Number 12</span>
<br/>
I have absolutely no idea if it is possile to get to know - maybe through Javascript or CSS, how many spans are displayed in a "row", to automate the odd-even-coloring, make it in a way responsive.
Check my Fiddle to maybe show better what I'm trying to get.
Don't you want to use any css framework? Like Bootstrap or Foundation? I hope that will make your work more easier.
Please go through the link.
https://getbootstrap.com/examples/grid/
It already has the solution for mobile device and medium screen.
I can't think of any way to pull it off with CSS, but here's a javascript solution. Browser support is a little off. Didn't realize you tagged jQuery in your post, but it should work on modern browsers at least:
window.addEventListener('resize', function(){
var cells = document.querySelectorAll('.odd,.even');
var activeClass='even', activeLine = 0;
for(var i = 0, len = cells.length; i < len; i++) {
cells[i].classList.remove('odd');
cells[i].classList.remove('even');
if(activeLine != cells[i].offsetTop + cells[i].offsetHeight) {
activeClass = (activeClass === 'even') ? 'odd' : 'even';
activeLine = cells[i].offsetTop + cells[i].offsetHeight
}
cells[i].classList.add(activeClass);
}
});
/* edit: forgot to dispatch the event.
jQuery makes this so much easier to write
than the monstrosity below. */
var event;
event = document.createEvent("HTMLEvents");
event.initEvent("resize", true, true);
window.dispatchEvent(event);
Demo here: http://jsfiddle.net/xh0o6gvy/1
Edit: Here is the jQuery version that Sunny put together found in a fiddle from the comment below. It's definitely a better way to go than the above code if compatibility with older browser versions is required.
function colorSpans() {
var containers = $('.span_container');
containers.each(function() {
var activeClass = 'even';
var activeLine = 0;
var cells = $(this).children('.odd, .even');
cells.each(function() {
$(this).removeClass('odd even');
var offset = $(this).offset();
var height = $(this).outerHeight();
if(activeLine != offset.top + height) {
activeClass = (activeClass === 'even') ? 'odd' : 'even';
activeLine = offset.top + height;
}
$(this).addClass(activeClass);
});
});
}
$(window).on('resize', function() {
colorSpans();
});
colorSpans();
Thanks everybody for your help and inspirations!
So just to round it up, here is the final function I am now using that works with fixed and variable container sizes and recolors container by container.
function colorSpans() {
var containers = $('.span_container');
containers.each(function() {
var activeClass = 'even';
var activeLine = 0;
var cells = $(this).children('.odd, .even');
cells.each(function() {
$(this).removeClass('odd even');
var offset = $(this).offset();
var height = $(this).outerHeight();
if(activeLine != offset.top + height) {
activeClass = (activeClass === 'even') ? 'odd' : 'even';
activeLine = offset.top + height;
}
$(this).addClass(activeClass);
});
});
}
An here is the fiddle: http://jsfiddle.net/z9db7p0t/1/
You could accomplish this with Javascript or plain CSS depending on the rest of your HTML/CSS.
Are the width of the span elements fixed? What about their parent container? If so, you should know where the breakpoints in your layout exist and easily target the elements via css within the proper media queries.
If the size is dynamic, you could update the classes on the spans by calculating how many spans could fit in a row. This would need to be called each time the page was resized however. Using jQuery:
$(function() {
var container = $('#span-container'),
spans = container.find('span');
$(window).on('resize', function(evt) {
var containerWidth = container.width(),
spanWidth = spans.width();
var howManyPerRow = Math.floor(containerWidth / spanWidth);
//reset rows
spans.removeClass('odd even');
var row = 'odd',
c = 1;
spans.each(function() {
$(this).addClass( row );
if( c % howManyPerRow == 0 ) {
row = (row == 'odd') ? 'even' : 'odd';
}
c++;
});
});
});
You are going to need to remove the <br /> tags for this to work correctly. Also, you should set white-space: nowrap; on the spans IMO.

How to think of a script that auto widens a search field when a username next to it gets too long

The goal is simple when a username gets too long on an account drop down menu how to make the search field reduce in width to make room for the longer name; the same is true when the name is short, how to make the form field fill up the empty space when a name is shorter.
I've started a pen here: http://codepen.io/MARS/pen/qtJsr
I'll be working on it throughout the day so there's no JS there now, but really i'm looking for ideas more than someone telling me exactly how to do it.
In pseudo code i'm guessing it would be something like this:
var username = $('#usernameID").length();
var search = $('#searchFieldId');
if(username > 34) {
make search bar this width (can be fixed because we have a cap of 34 characters so it will never get bigger than that)
}
if(username < 34){
make search field as wide as need be to be next to the elements without there being significant space
}
Here are some screenshots:
I'm almost thinking a while statement might be best but i'm new to javascript and my thinking is slow when putting the dots together.
There are icon placeholders that are to the right of the form field and to the left of the username, this is not so much part of the problem as it is something i need to account for.
Can anyone provide any suggestions? Thanks.
SOLUTION CODE THAT WORKED:
var userWidth = $('#userOptions');
var searchField = $('#txtFamilySearch');
var icons = $('.icons');
$('#txtFamilySearch').css("width", 740 - (userWidth.width() + icons.width()));
You mentioned you were looking for ideas more so than answers. If I was writing this page I would first set a specific width on the Search bar and the Username field. This way the two fields combined add up to a specific width: 700px Search, 200px Username = 900px work space. Then create an onload call on the body tag to run a function that checks the width of the username. So the username will be in a span with an id of "username"
function onloadFunct() {
var userLength = document.getElementById("username").innerHTML.length();
if (userLength > x) {
// we want the search to shrink
var Y = userLength - standardLength;
// I get the number of characters past what the textbox can normally hold
var Z = Y * pixelsPerCharacter;
// I multiply the excess characters by the estimated space they will take up
document.getElementById("search").width = document.getElementById("search").width - Z;
document.getElementById("username").width = document.getElementById("username").width + Z;
} else {
// we want the search to grow
// same as above but I reverse the - and + signs
}
}
I hope this helps, the point of keeping both the search bar and the username field equal to a specific width is to avoid taking up the space that is needed for the icon placeholders.
Example variables:
standardLength = 40; // 40 characters can fit comfortably within the 200 space
pixelsPerCharacter = 5; // each character will take up about 5 pixels, so for every character past the bounds we will add 5
ALTERNATIVELY:
You can take off the width of username field, and after the page has loaded use
javascript: document.getElementById("search").width = 900 - document.getElementById("username").width;
I'm lazy to write full solution. I think, that you should use size property of input. If size is used, then you shouldn't think about pixel length of input and overall width; here, only left field rules
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="container" style="width:500px">
<input size="30" id="fname" type="text" placeholder="Enter First Name"></input>
<input size="30" id="lname" type="text" placeholder="Enter Last Name"></input>
</div>
<script>
var fname = document.getElementById('fname'),
lname = document.getElementById('lname'),
fSize = fname.size,
lSize = lname.size;
document
.getElementById('fname')
.addEventListener('keyup', function (e) {
var len = this.value.length;
if (len > fSize) {
this.size += 1;
lname.size -= 1;
}
});
document.getElementById('lname').addEventListener('keypress', function (e) {
alert('lname');
});
</script>
</body>
</html>
My approach on similar use cases is like:
create/get/copy element with auto width
add element to dom
get width of the rendered element
do whatever you want to other elements depending on the width
Note: you would eventually have to consider margin and padding.
Here's a working JS fiddle with the JavaScript:
http://jsbin.com/lorajuza/7/edit?js
Code:
$('#txtFamilySearch').on('keydown', function() {
var input = $(this),
inputWidth = input.val().length;
if ( inputWidth > 34 ) {
input.attr('size', inputWidth );
}
else {
input.attr('size', 50)
}
});
You will need to add responsive CSS to ensure the buttons stay on the same line. I would also set a max limit for the input size, but that's up to you.

Dynamic Table Width

I have a table cell in which other tables are displayed (with background colors). The inner tables aren't always shown; they can be hidden via a button (change class with jQuery). Now I want the outer cell to always be filled with color. That means if only one table is displayed, its width should be 100%. When two are displayed, each width should be 50%, and so on.
How am I supposed to solve this?
Here's an example:
...
<td>
<table class="show"><tr><td></td></tr></table>
<table class=""><tr><td></td></tr></table>
<table class="show"><tr><td></td></tr></table>
</td>
...
In this case, the width should be 50%
You can change the width value with Jquery.
var count_table = $(".show").length; // count ".show" elements
$(".show").each(function{ // iteration on each ".show"
var width = 100/count_table; // % value of new width
$(this).css("width", width+"%"); // CSS modification
});
This code is just adapted for one TD element. You need to iterate on each "td" too.
(I hope I answered your problem)
To change the width of your elements you can use jquery.
Here's the page explaining how.
Here is another way: http://jsfiddle.net/ypJDz/1
A bit too complicated for what you need, but a great deal of possibility to expand.
function resizeTables() {
var baby = $("td > table.show"),
amount = baby.length,
mother = $("body");
baby.width(function () {
var w = mother.width() / amount;
return w;
});
}
resizeTables();
$("button").click(function () {
var $this = $(this),
ID = $this.index() + 1;
$("td > table:nth-child(" + ID + ")").toggleClass("show");
resizeTables();
});

How to count numbers of line in a textarea

I want to make a dynamic textarea, it should increase in rows as the content increase.
I am using this code:
$("#text_textarea").keyup(function(e) {
//splitting textarea value wrt '\n' to count the number of lines
if ($(this).val().lastIndexOf('\n')!=-1)
var x = $(this).val().split('\n');
$(this).attr( "rows" , x.length+1 );
});
But it fails when user continues to write without giving any new line \n (pressing Enter).
var keyUpTimeout = false; // Required variables for performance
var keyupTimer = 0;
$("#text_textarea").keyup(function(e) {
var cooldownTimeout = 500;
//Set the cooldown time-out. The height check will be executed when the user
// hasn't initiated another keyup event within this time
var ths = this;
function heightCheck(){
keyupTimer = false;
// Reset height, so that the textarea can shrink when necessary
ths.style.height = "";
// Set the height of the textarea
var newheight = this.scrollHeight + 2;
ths.style.height = newheight + "px";
}
if(keyupTimeout){ //Has a cooldown been requested?
clearTimeout(keyupTimer); //This+next line: Refresh cooldown timeout.
keyUpTimer = setTimeout(heightCheck, cooldownTimeout);
return; //Return, to avoid unnecessary calculations
}
// Set a cooldown
keyupTimer = setTimeout(heightCheck, cooldownTimeout);
keyupTimeout = true; //Request a cooldown
});
This piece of script will change the height of the textarea to fit the text inside.
Update
I have added an additional feature: To improve performance (changing the CSS height requires a significant amount of computer power), I have added a cooldown effect: The height check will only be executed when the user hasn't initiated a keyup event for 500 milliseconds (adjust this value to meet your wishes).
read this,
Textarea Height increase
TextAreaExpander (Demo)
autoResize Plugin
JQuery Elastic
You should use the attribute wrap='hard' on your textarea.
I write this code. what about it..
$("#text_textarea").keyup(function(e) {
var textarea_height = Number($(this).css('height').replace("px", ""))+4;
var scroll_height = this.scrollHeight;
if(textarea_height < scroll_height ){
$(this).css('height' ,"");
var x = Number(scroll_height) + 3;
if(x != $(this).height())
$(this).css("height", x+"px");
}
});

Categories