Find div width that makes the text inside not wrapped - javascript

I built a CRM with some javascript to adjust the columns widths as the user wants, but I would like to have a button to automatically adjust the width of all column.
The idea is to check each div to verify if the text is wrapped and if so, increase the div width (within a given limit) or reduce in the opposite case. Something like that:
while(div.contentTextWrapped && parseInt(div.style.width)>50)
{
div.style.width=parseInt(div.style.width)-5+"px";
}
while(div.contentTextWrapped && parseInt(div.style.width)<500)
{
div.style.width=parseInt(div.style.width)+5+"px";
}
But I don't know such feature. Maybe I could set the white-space to nowrap and check the width but I need the content is not an element, or maybe I need to add a div inside and then I could check its width and compare ?

I think you have to calculate number of lines and then adjust width of object. There are a lot of ways to do that, here's one approach:
function findWidth(obj, minW, maxW) {
let lines, ref, lineHeight, wdt, dif=10, done=false;
// Get line height from myDummy
ref=document.getElementById('myDummy')
lineHeight=ref.offsetHeight;
if(lineHeight==0) return
// Assign min widht to start
wdt=minW;
obj.style.width=wdt+'px';
lines=Math.round(obj.offsetHeight/lineHeight);
while(lines>1) {
// Get current width and increase or assign max / min and exit
wdt=parseInt(obj.style.width);
if(wdt+dif>maxW) {
wdt=maxW;
done=true;
} else if(wdt<minW) {
wdt=minW;
done=true;
} else {
wdt+=dif;
}
obj.style.width=wdt+'px';
if(done) break;
lines=Math.round(obj.offsetHeight/lineHeight);
}
}
// Some tests...
findWidth(document.getElementById('myDiv1'), 25, 200);
findWidth(document.getElementById('myDiv2'), 25, 200);
findWidth(document.getElementById('myDiv3'), 25, 200);
#myDummy {
visibility: hidden;
}
div {
border: 1px solid crimson;
}
<div id="myDummy"> </div>
<div id="myDiv1">
This is some text...
</div>
<div id="myDiv2">
This is some text... with more and more and more and more and more...
</div>
<div id="myDiv3">
T...
</div>

You can try to find width of one character. then get whole text of your div and calculate total size of div:
const singleCharWidth = 3; // in px
const textLength = div.textContent.length;
div.style.width = `${textLength * singleCharWidth}px`;
If you want to read more about calculating text width you can read more about this here: Calculate text width with JavaScript

Related

How to fill progress bar based on number of letters typed?

I am trying to make an input box that has a div on the bottom which will act sort of a progress bar to tell you when you have enough characters typed.
I can't get this animation to work, even though I thought it would be a lot easier when I decided to try this project.
Please let me know what is wrong with my code. Thanks!
<div id='cntnr'>
<div id='inptDiv'>
<input id='inpt1'>
<div id='prgInd'></div>
</div>
</div>
var main = function() {
var inptAmnt = document.getElementById('inpt1').value;
if(inptAmnt.length === 1) {
$('#prgInd').css('width', 25);
}
}
$(document).ready(main);
I also tried this code first but it didn't work either:
var main = function() {
var inptAmnt = document.getElementById('inpt1').value;
if(inptAmnt.length === 1) {
$('#prgInd').animate({
width:25
},200 )
}
}
$(document).ready(main);
JSFiddle: https://jsfiddle.net/qcsb53ha/
You can use jQuery to listen to the change, keyup and paste events of your text input.
Then, work out a percentage, based on your desired input length; and use this percentage to set the width of the progress bar.
If the "percentage" is above 100 - just reset it to 100 again. jQuery code is below:
var desiredLength = 4; // no jokes please...
// Listen to the change, keyup & paste events.
$('#text-box').on('change keyup paste', function() {
// Figure out the length of the input value
var textLength = $('#text-box').val().length;
// Calculate the percentage
var percent = (textLength / desiredLength) * 100;
// Limit the percentage to 100.
if (percent > 100) {
percent = 100;
}
// Animate the width of the bar based on the percentage.
$('.progress-bar').animate({
width: percent + '%'
}, 200)
});
See the working JSFiddle here : https://jsfiddle.net/jqbka5j8/1/
I've included normal code for setting the width, and the code for animating the width. You can comment/uncomment the necessary ones and test appropriately.
Hope this helps!
There's no need the use of javascript, you can use only pure CSS and Content Editable:
HTML
<div>
<span contenteditable="true">sdfsd</span>
</div>
CSS
span
{
border: solid 1px black;
}
div
{
max-width: 200px;
}
JsFiddle example

Insert inline element and animate shift to left

I've been trying to solve this problem for a week now and it seems basic, so maybe I'm missing something.
I want to have a div centered on the screen (or its container), and then insert a second div to the right of it, so that afterwards the two of them are centered (space on each side is equal).
Inserting the second div is not a problem, but I need the first block to slide over to where its going to be after the new block is inserted.
http://jsfiddle.net/rdbLbnw1/
.container {
width:100%;
text-align:center;
}
.inside {
border:solid 1px black;
width:100px;
height:100px;
display:inline-block;
}
$(document).ready(function() {
$("#add").click(function() {
$(".container").append("<div class='inside'></div>");
});
});
<div class="container">
<div class="inside"></div>
</div>
<input id="add" type="button" value="add"/>
Do I need to explicitly calculate where the original box is going to end up and then animate that, or is there a better way to do it?
I like your question so decide to write this:
$(document).ready(function() {
var isInAction = false;
var intNumOfBoxes = 1;
var intMargin = 10;
$containerWidth = $(".container").width();
$insideWidth = $(".inside").width();
$(".inside").css('margin-left',($containerWidth - $insideWidth - intMargin)/2 + 'px');
$("#add").click(function() {
if (!isInAction){
isInAction = true;
intNumOfBoxes +=1;
$(".current").removeClass("current");
$(".container").append("<div class='inside current'></div>");
$('.inside').animate({
'margin-left': '-=' + ($insideWidth + intMargin)/2 + 'px'
}, 300, function () {
$(".current").css('margin-left',($containerWidth + ((intNumOfBoxes - 2) * ($insideWidth + intMargin)))/2 + 'px');
$(".current").fadeIn(500,function(){
isInAction = false;
});
});
}
});
});
Also add this class in CSS:
.current {
display:none;
}
You don't need to change variables in JS code except intMargin. you can change this var to set margin between boxes.
Note: This code works fine on older browsers too and not need to support CSS3 features like transition.
Update: Some bugs like repeated clicks fixed.
Check JSFiddle Demo
First, we can animate only things that have explicit numerical values such as width, left or margin. We can't animate things like alignment (which actually use the same margin property but implicitly, never mind). So if we know width of inserted div let's just add it to our container.
1) Let's centre container itself and add transition to it
.container {
width: 102px; /* set explicit width; 102 - because of borders */
margin: auto; /* set margin to 'auto' - that will centre the div */
transition: width 0.5s;
}
2) Then increase the width when add div
$(".container").width($(".container").width() + 102);
3) But wait! If we add div to too narrow container it will be added to bottom not to right. So we need another container set to appropriate width before.
See final example on JSFiddle.
BTW, remove all line breaks and tabs from your code when you use inline-block, because it will cause spaces between your blocks.

How to set the font-size to 100% the size of a div?

I have a div with a static size. Sometimes longer text than the div will be placed there. Is there anyway to achieve the text fitting the div width at all times through JavaScript alone? I am aware there are jQuery fixes but need a pure JS solution in this case.
Even if you have a link to a demo/tutorial that would be helpful, thanks.
Here you go, this should do what you want: JSFiddle
Basically the key here is to check the output.scrollHeight against output.height. Consider the following setup:
HTML:
<button onclick="addText(); resizeFont()">Click Me to Add Some Text!</button>
<div id="output"></div>
CSS:
div {
width: 160px;
height: 160px;
}
This creates a square div and fills it with a randomly long string of text via the addText() method.
function addText() {
var text = "Lorem ipsum dolor amit",
len = Math.floor(Math.random() * 15),
output = document.querySelector('#output'),
str = [];
for (; --len;)
str.push(text);
output.innerHTML = str.join(', ');
}
The magic lies in the resizeFont() function. Basically what this does is, once the text has been added, it sets the fontSize of the div to be equal to its own height. This is the base case for when you have a string of 1 character (i.e. the fontSize will equal the height). As the length of your string grows, the fontSize will need to be made smaller until the scrollHeight equals the height of the div
function resizeFont() {
var output = document.querySelector('#output'),
numRE = /(\d+)px/,
height = numRE.exec(window.getComputedStyle(output).height)[1],
fontSize = height;
// allow div to be empty without entering infinite loop
if (!output.innerHTML.length) return;
// set the initial font size to the height of the div
output.style.fontSize = fontSize + 'px';
// decrease the font size until the scrollHeight == height
while (output.scrollHeight > height)
output.style.fontSize = --fontSize + 'px';
}
The nice thing about this method is that you can easily attach an event listener to the resize event of the window, making the text dynamically resize as the user changes the window size: http://jsfiddle.net/QvDy8/2/
window.onload = function() {
window.addEventListener('resize', resizeFont, false);
}

Full height content with the smallest possible width

I would never think this is possible, but there are a lot of clever people here so I thought I'd ask. I'm looking for a way to have a full-height container whose width depends on how much content there is. I want the text to fill the area taking up the full height while using the smallest possible width. The height is known and hard-coded, the amount of content is not.
I'm working with something like this:
<div>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled....</p>
</div>
div {
background:red url(http://lorempixel.com/600/400/);
float:left;
width:600px;
height:400px;
}
p {
background:#fff;
padding:20px;
margin:20px;
}
Normally content fills the page from top to bottom:
What I'm looking for is sort of the opposite, filling in left-to-right:
With less content, it should look like this:
Using full hard-coded height with width:auto produces this effect:
Is there any way to have the text fill the height with the smallest possible width, without hard-coding a width or having text overflow? It seems impossible and I have no idea how to approach it. Javascript/jQuery solutions welcome.
What I have in mind is a simple jQuery solution: in a while loop, set the condition such that the loop is run whenever the height exceeds the container height. In the loop, you increase the width of <p> pixel by pixel until the height no longer exceeds container height :)
$(document).ready(function() {
// The 400-80 is because you have to subtract the container padding and the element's own padding
while($("div > p").height() > 400 - 80) {
currentWidth = $("div > p").width();
$("div > p").width(currentWidth + 1);
}
});
http://jsfiddle.net/teddyrised/RwczR/4/
I have made some changes to your CSS, too:
div {
background:red url(http://lorempixel.com/600/400/);
float:left;
overflow: hidden;
width:600px;
height:400px;
padding: 20px;
box-sizing: border-box;
}
p {
background:#fff;
padding: 20px;
width: 1px;
}
This is not too difficult to do with JavaScript. I have no idea how to do it without JS (if that's even possible).
You can use another "invisible" div to measure dimensions until it gets to the 320px height while reducing its with by a set amount (even 1 pixel at a time, if you want to be as precise as possible).
var $measurer = $("<div>").css({'position': 'fixed', 'top': '100%'})
.text($("p").text()).appendTo('body');
var escape = 0;
while ($measurer.height() < 320) {
console.log($measurer.height());
$measurer.width(function (_, width) { return width - 1; });
console.log($measurer.width());
escape++;
if (escape > 2000) {
break;
}
}
$("p").width($measurer.width());
$measurer.remove();
http://jsfiddle.net/RwczR/2/
Try this:
var p = $('p');
var height = parseInt(p.height())-40;
p.height('auto');
p.width('auto');
for(var i=p.width(); i--; ) {
p.width(i);
if (p.height() > height) {
p.height(height+20);
p.width(i-1);
break;
}
}
p.height(height);
http://jsfiddle.net/RwczR/6/
You can use jQuery/JavaScript and checking the client vs the scroll heights keep increasing the width until it fits the text, similar to the below.
You need to also set overflow: hidden; in the CSS on the p tag for the scrollHeight to give you the actual height including the overflow.
The below code also takes margin and padding into account for both; height and width and adjusts accordingly.
Changing the height of the outer div ajdust accordingly.
$(document).ready(function(){
var $container = $("div");
var containerHeight = $container.height();
var containerWidth = $container.width();
var $textWrapper = $(">p", $container);
var paddingMarginHeight = $textWrapper.outerHeight(true) - $textWrapper.innerHeight();
var paddingMarginWidth = $textWrapper.outerWidth(true) - $textWrapper.innerWidth();
$textWrapper.innerHeight(containerHeight - paddingMarginHeight);
//SetMinWidth();
var maxWidth = containerWidth - paddingMarginWidth;
var visibleHeight = 0;
var actualHeight = 0;
for(i = 50; i <= maxWidth; i++){
$textWrapper.innerWidth(i);
visibleHeight = $textWrapper[0].clientHeight;
actualHeight = $textWrapper[0].scrollHeight;
if(visibleHeight >= actualHeight){
break;
console.log("ouyt");
}
}
});
DEMO - Grow width until text is fully visible
We can give the paragraph an overflow:auto;.
If the paragraph needs a vertical scroll bar, it will create one.
The trick is to keep tightening the width, until the scroll bar is created.
var hasScrollBar = false;
var p = document.getElementById('myParagraph');
while(!hasScrollBar)
{
if(p.scrollHeight>p.clientHeight)
{
//Has Scroll Bar
//Re-Increase Width by 1 Pixel
hasScrollBar=true;
p.style.width=(p.clientWidth+1)+"px";
}
else
{
//Still no Scroll Bar
//Decrease Width
p.style.width=(p.clientWidth-1)+"px";
}
}

A jQuery/javascript auto-sizable grid control

I am implementing a jquery file upload page. While a user is adding files, I want them to be getting listed in a form of an icons in an auto-sizable grid.
Auto-sizable means it provides maximum space for containing elements. When there is two objects - it woud look like (I know i will have to handle image resizing myself):
When several are added:
Is there a "grid control" (jquery perhaps) that does at least close to what I need sizing wise?
First of all, please keep in mind that I'm a jQuery newbie and this is my first post on Stackoverflow :)
I've the same problem and I've try to fix it using jQuery and CSS. This is my body tag content:
<div id="controls">
Controls:
<button id="add">+</button>
<button id="del">-</button>
Current ratio:
<span id="value"></span>
<button id="increase">+</button>
<button id="decrease">-</button>
Referred to:
<form style="display: inline;">
width<input type="radio" name="maximize" value="width">
height<input type="radio" name="maximize" value="height">
</form>
</div>
<div id="elements" style="width: 500px; height: 300px; background: black;">
</div>
<script>
ratio = 1;
ratioWidth = true;
function autoresize() {
boxes = $('#elements').children().size();
rows = Math.ceil(Math.sqrt(boxes/ratio));
columns = Math.ceil(boxes/rows);
if (!ratioWidth) {
tmp = rows;
rows = columns;
columns = tmp;
}
$('#elements').children().css('width', 100/rows+'%');
$('#elements').children().css('height', 100/columns+'%');
}
function add() {
red = Math.floor(Math.random()*256);
green = Math.floor(Math.random()*256);
blue = Math.floor(Math.random()*256);
color = 'rgb('+red+','+green+','+blue+')';
$('#elements').append("<div style=\"background: "+color+"; float: left;\"></div>");
autoresize();
}
function update() {
$('#value').text(ratio);
autoresize();
}
function remove() {
$('#elements').children().last().remove();
update();
}
function increase() {
ratio++;
update();
}
function decrease() {
if (ratio > 1) {
ratio--;
update();
}
}
$(document).ready(function() {
$('#add').click(add);
$('#del').click(remove);
$('#increase').click(increase);
$('#decrease').click(decrease);
if (ratioWidth) value = 'width'
else value = 'height'
$('input[type=radio]').filter('[value='+value+']').attr('checked', true);
$('input[type=radio]').live('change', function() {
if ($(this).val() == 'width') ratioWidth = true
else ratioWidth = false;
autoresize();
});
update();
//$(window).bind("resize", autoresize);
});
</script>
You could remove the background color stuff and put your icons centered in those boxes.
If you find a better way of if you improve this code, please let me know :)
Edit 1 - I've added some Math.floor(...) to remove a bug when boxes side has repeating decilmals: very size is a simple integer. Now dimensions are fetched from the container div, I use black as background color for the main container and I've noticed a little issue: sometimes I see a black border near the little boxes, even if I don't set any background color. Could it be a Firefox rendering glitch?
Edit 2 - Now it's possible to set if you prefer to auto-expand horizontally, vertically, or none of them. I've tried to write a better code, and I've commented autoresize when the window is resized (use it only if your container box hasn't a fixed height/width). I think that now it needs an ratio option, in order to specify if width have to be twice longer for example. Live example: http://experimental.frafra.eu/maxarea2.html
Edit 3 - New code! Better graphical representation and a new parameter: ratio. Ratio is a coefficient between the ratio between main container width/height and the elements one. Live example: http://experimental.frafra.eu/maxarea3.html

Categories

Resources