A jQuery/javascript auto-sizable grid control - javascript

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

Related

Find div width that makes the text inside not wrapped

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

Can you set the size of an element using getBoundingClientRect

I have a button that gets resized on the mouse enter event. I am wondering if its possible to resize it based on its height received from getBoundingClientRect().height.
This is what I've tried so far with variations of this but nothing seems to work
btn.onmouseover = function(){
let h = this.getBoundingClientRect().height;
this.style.width = "100%";
if(h != this.getBoundingClientRect().height)
{
this.getBoundingClientRect().height = h;
}
this.style.right = "4%";
}
What happens is the button resizes when the mouse is over the button due to the text inside of it being moved from two lines to one so I was wondering if there is a function call similar to getBoundingClientRect() where i can set the height of the button based on the height I get from h. This way the text inside the button being moved from 2 lines to one doesn't resize the whole button on mouseover.
Also setting the height from h to the style height of the button creates a weird offset so that's not really a viable solution for me in this scenario
I'm confused by this code. You are checking if the height you just obtained from getBoundingClientRect is equal to the height from getBoundingClientRect, and of course it will always be. And no, you can't possibly change the size of something by updating the information in the size you got from calling getBoundingClientRect. Anyway, if you really want to do something in JS relating to hovering, you need to use mouseenter and mouseleave, not mouseover.
But actually, you should be able to do this entirely in CSS.
button { width: 200px; height: 3em; }
button:hover { width: 400px; }
<button>Hi, I'm a button with some pretty long text</button>
If you really want to handle the mouse events yourself, then
const button = document.querySelector('button');
button.addEventListener('mouseenter', () => {
button.style.height = button.offsetHeight + 'px';
button.style.width = '600px';
});
button.addEventListener('mouseleave', () => {
button.style.width = button.style.height = '';
});
button { width: 240px; }
<button>Button with some pretty long text which will wrap</button>

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

Toggle iframe height/width

So I would like to make a toggle button for 2 different sizes of my frame.
I was able to make 2 simple buttons for resizing the iframe with these simple functions
function changeframe_big()
{
document.getElementById('frame').width = 1000;
document.getElementById('frame').height = 600;
}
function changeframe_small()
{
document.getElementById('frame').width = 640;
document.getElementById('frame').height = 360;
}
(Please ignore the ratios, I'm just testing it.)
And the buttons ...
<button id="change_big" onClick="changeframe_big()">BIG</button>
<button id="change_small" onClick="changeframe_small()">SMALL</button>
So, and basically I would like to make only one button, which would toggle between these two sizes.
I'm somehow struggling to get this done.
I appreciate any help.
Thank you.
assuming that your given code works, you could do the following:
your HTML:
<button id="toggle" onClick="toggle()">Toggle</button>
your JS:
var small=false;
function toggle()
{
if(small){
document.getElementById('frame').width = 1000;
document.getElementById('frame').height = 600;
small=false;
}
else{
document.getElementById('frame').width = 640;
document.getElementById('frame').height = 360;
small=true;
}
}
basically what this code does is it checks if "#frame" is small or big (assumed that the default size is big), and then toggles it to the other size.

Looping a dynamic text sizing function jquery/javascript

I'm trying to dynamicly resize text within a div so that the text does not run outside of the box it was intended for. I'm trying to do this so that I can make a printable form.
Geeky Monkey has a jquery plugin that works great but my problem is I can't loop it to do it over and over for different div's to make sure they're all properly sized. If I make all my div's the same class they all get the same text size so obviously this doesn't work.
This is Geeky Monkey's unedited code
(function($) {
$.fn.textfill = function(options) {
var fontSize = options.maxFontPixels;
var ourText = $('span:visible:first', this);
var maxHeight = $(this).height();
var maxWidth = $(this).width();
var textHeight;
var textWidth;
do {
ourText.css('font-size', fontSize);
textHeight = ourText.height();
textWidth = ourText.width();
fontSize = fontSize - 1;
} while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
return this;
}
})(jQuery);
$(document).ready(function() {
$('.jtextfill').textfill({ maxFontPixels: 36 });
});
And the html code that goes with it
<div class='jtextfill' style='width:100px;height:50px;'>
<span>My Text Here</span>
</div>
This is what I tried to do to change it and make it a loop
$(document).ready(
for(i=1;i<3;i++){
function() {
$('.jtextfill' + i).textfill({ maxFontPixels: 72 });
})};
And the html to go with my revision
<div class='jtextfill1' style='width:400px;height:200px;'>
<span>THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG</span>
</div>
<div class='jtextfill2' style='width:50px;height:25px;'>
<span>THIS IS THE SECOND PART OF MY TEXT</span>
</div>
As I'm sure you could guess it's not working. jquery does still confuse me so please forgive me if it is an obvious mistake. Any help would be greatly appreciated.
Thanks
OK, as I understand it you want to have various divs each with a different class so that you can give each its own font size (and potentially other individual properties). You want to be able to process each div to - if necessary - shrink the font of the span in the div so that it will fit in the div without overflowing.
If so, calling the textfill() method in a loop but passing the same maxFontPixels parameter to it for every div won't work, because obviously they'll all then start out with the same default maximum font size. You could update your loop to pass in different font sizes, but instead I would suggest changing the textfill() to start with the current font-size of the div, rather than taking it as a parameter.
Then, rather than trying to do a loop to repeatedly call textfill(), you can use a single JQuery selector that selects all of the divs you want to process. Following is just one way to do what I've described. (Note: I haven't actually tested it, but I hope it will get you on your way.)
EDIT: In the original code there was also a basic problem with the .textfill plugin, that (as with any JQuery plugin) its this was a JQuery object that - depending on the selector - may be a list of many DOM elements, but it was treating it as a single DOM element. Just needed to add a this.each() loop around the rest of the function code and it works.
<style>
.someclass1 { font-size: 36px; }
.someclass2 { font-size: 48px; }
</style>
<div class='someclass1 jtextfill' style='width:400px;height:200px;overflow:hidden;'>
<span>THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG</span>
</div>
<div class='someclass2 jtextfill' style='width:50px;height:25px;overflow:hidden;'>
<span>THIS IS THE SECOND PART OF MY TEXT</span>
</div>
<script>
(function($) {
$.fn.textfill = function() {
// EDIT: added the .each()
this.each(function() {
var fontSize = parseInt($(this).css('font-size'),10);
var ourText = $('span:visible:first', this);
var maxHeight = $(this).height();
var maxWidth = $(this).width();
var textHeight;
var textWidth;
do {
ourText.css('font-size', fontSize + "px");
textHeight = ourText.height();
textWidth = ourText.width();
fontSize = fontSize - 1;
} while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
// EDIT: added the closing brackets for the .each
});
return this;
}
})(jQuery);
$(document).ready(function() {
$('.jtextfill').textfill();
});
</script>
Notes: in this case the 'jtextfill' class isn't actually defined in the stylesheet, it is used solely as a convenient way to let JQuery select all of the divs that you want to process. The actual font stylings are applied via the 'someClass1', etc., classes. (In case you weren't aware, HTML/CSS allows you to apply multiple classes to the same element.)
I've changed only twothree things in the textfill() method: (1) I get the font-size from the element, which should be returned as a string like '36px', then use parseInt to grab the integer part of that (throwing away the 'px'). (2) When the font is set inside the loop I append 'px' back onto the font size. (3) Added a .each() loop within the plugin function.

Categories

Resources