jQuery CSS font-size - javascript

How do I auto resize the font-size of a <td> if the content goes into second line? I know how to increase/decrease font size using CSS and jquery but how to automatically make the font-size smaller if a particular or all the td's with a specific class name text gets longer then one line.
<div style="overflow: hidden;" id="parentDiv" class="scroll">
<div id="4" >
<table id="t4" class="Table">
<tbody>
<tr>
<td id="b4" class="bY"><table id="inner1" width="100%" cellpadding="3">
<tbody>
<tr>
<td class="code" id="code4" width="172"></td>
<td class="Num" id="Num4" width="50"></td>
<td colspan="2" class="Name" id="Name"></td>
</tr>
<tr>
<td class="code" width="172"> </td>
<td> </td>
<td class="serial" width="110"></td>
<td class="serial" width="322"></td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>
</div>

You want .filter(). For most elements this should work:
$(".myClass").filter(function()
{
var el = $(this);
el.css("white-space", "nowrap");
var lineHeight = el.height();
el.css("white-space", "");
return el.height() > lineHeight;
}).css("font-size", "10pt");
Dealing with tables, all the cells in a row have the same height, so check the value of a child element. Eg, wrap everything in a div. However, if you must act on a <td> directly:
$(function()
{
$(".myClass td").filter(function()
{
var el = $(this);
el.closest("tr").andSelf().css("white-space", "nowrap");
var lineHeight = el.height();
el.css("white-space", "normal");
var textWraps = el.height() > lineHeight;
el.closest("tr").andSelf().css("white-space", "");
return textWraps;
}).css("font-size", "10pt");
});

There isn't a straightforward way to get the width (in pixels) of text content. You can however get a reasonable estimate by multiplying the number of characters by the average pixel width of each character - this will vary depending on the font, and works best for fixed-width fonts like Courier. This also assumes that all the content is simple text without additional formatting.
Most fonts have a character width less than the height, so assuming width = height will definitely work.
Example:
var fontSize = parseInt($('.my-td-class').css('font-size')); // get default font size
function updateFont() {
var e = $('#some-element');
while (e.text().length * fontSize > e.width()) {
fontSize *= 0.8; // reduce to 80%
e.css('font-size', fontSize + 'px');
}
}
Edit: Based on the other answers, you could apply this technique to the height as well. Just make sure that the width/height comparison reflects the current font size and not any hard-coded value.

var newFontSize = 8
if $('td').filter(function() {
return $(this).height() > 20
}).css("font-size", newFontSize);
Play with the height > 20 and newFontsize to get what you want.

Related

Count Table Rows Hidden In Overflow with Javascript

I have a bootstrap 3 dashboard where I am hiding the overflow in a particular div. I need to be able to identify the number of table rows hidden in the overflow that are not visible in the div. jQuery method preferred but vanilla JS also fine.
have been trying to sort this out and have not been able to find any ways so far to count the number of rows that are hidden in overflow.
NB: There is no markup difference between the rows that are visible and those that are not visible as CSS is used to hide the excess rows using overflow: hidden; on the parent DIV.
Thanks.
Additional #1
Here is the HTML I am working with. The height is set by javscript at runtime.
<div id="jobs-list" class="box-body no-padding job-list" style="overflow: hidden;">
<table class="table">
<tbody>
<tr>
<th>Account</th>
<th class="text-center">Due</th>
</tr>
<tr>
<td>
Customer 1 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 2 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 3 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 4 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center">-- TOMORROW --</td>
</tr>
</tbody>
</table>
</div>
<div class="box-footer text-center">
152 More Jobs
</div>
As you can see in the example above I am using a bootstrap 3 box to contain the data. The height of .box-body is set using javascript (which works fine already and is based on the window height). By using the overflow: hidden; CSS rule instead of showing scroll bars on .box-body the overflow is hidden and not visible. I need to be able to adjust the text in .box-footer using javascript to identify the number of rows that are not visible.
Now there is a mathematical approach to this problem, suppose that all the children have the same height (or width, depends on your aligning) :
console.log($('#main div').length - $('#main').height()/$('#main div').height());
#main {
height:200px; /*Suppose 200px*/
overflow:hidden;
}
#main div {
height:100px;
border:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<div>
Hello 1
</div>
<div>
Hello 2
</div>
<div>
Hello 3
</div>
<div>
Hello 4
</div>
<div>
Hello 5
</div>
</div>
Thanks for all the answers...
I was able to find a way to do this using jQuery and a jQuery extension by Kevin Marx.
Firstly you need to add the jquery.overflowing.js plugin to the page...
/* Overflowing.js
*
* A plugin based on Elving Rodriguez's Overflowed
* http://elvingrodriguez.com/overflowed
*
*/
(function($){
$.fn.overflowing = function(options, callback){
var self = this
var overflowed = []
var hasCallback = callback && typeof callback === 'function' ? true : false;
var status = false
this.options = options || window
this.each(function(){
var $this = $(this)
elPosition = $this.position()
elWidth = $this.width()
elHeight = $this.height()
var parents = $this.parentsUntil(self.options)
var $parentsTo = $(self.options)
parents.push($parentsTo)
for(var i=0; i<parents.length; i++){
var parentPosition = $(parents[i]).position()
var parentWidth = $(parents[i]).width()
var parentHeight = $(parents[i]).height()
if ( elPosition.top<0
|| elPosition.left<0
|| elPosition.top>(parentHeight+parentPosition.top)
|| elPosition.left>(parentWidth+parentPosition.left)
|| (elPosition.top + elHeight) > (parentHeight+parentPosition.top)
|| (elPosition.left+elWidth) > (parentWidth+parentPosition.left)){
status = true
$(parents[i]).addClass('overflowed')
overflowed.push(parents[i])
if (hasCallback) callback(parents[i])
}
}
if($this.parents(self.options).hasClass('overflowed')) $this.addClass('overflowing')
})
if (!hasCallback) return overflowed.length > 1 ? overflowed : status
}
})(jQuery)
Then you run...
$("tr").overflowing("#jobs-list");
Which through the overflowing plugin adds the class overflowing to each overflowing row (first selector) within the target parent (second selector).
At this point it is a simple case of using jQuery's .length property and a selector to target only the .overflowing classes within the target object you are wanting to calculate for, ie...
var hiddenRows = $("#jobs-list .overflowing").length;
I'm unsure by what you mean by 'hidden by overflow'. Does that mean include stuff that's partially hidden, or things that are fully hidden only? My solution includes partially hidden as 'not hidden'.
Regardless, offset is your best solution.
let jobs = $("#jobs-list");
let offset = jobs.offset().top;
let height = jobs.height();
let tr = $("tr", $("#jobs-list")).toArray();
let stopped = 0;
for (let i in tr)
{
let total_offset = $(tr[i]).offset().top - offset;
if (total_offset >= height)
{
stopped = i;
break;
}
}
console.log("hidden:", tr.length - stopped);
#jobs-list {
height: 80px;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="jobs-list" class="box-body no-padding job-list" style="overflow: hidden;">
<table class="table">
<tbody>
<tr>
<th>Account</th>
<th class="text-center">Due</th>
</tr>
<tr>
<td>
Customer 1 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 2 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 3 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 4 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center">-- TOMORROW --</td>
</tr>
</tbody>
</table>
</div>
<div class="box-footer text-center">
152 More Jobs
</div>
Found this: Count List Items shown on screen and not overflow
Working jQuery example: https://jsfiddle.net/Twisty/jzmqfeyj/
JavaScript
$(function() {
//Add random count of jobs
var i = 0;
for (i = 0; i < Math.floor(Math.random() * 100); i++) {
$("#jobs-list tbody").append($("#jobs-list table tbody tr:last").clone());
}
console.log("Created", i, "Jobs");
console.log("Total", $("#jobs-list table tbody tr:not('.header')").length, "Jobs");
var mh = $("#jobs-list").height();
var overflowed = $("#jobs-list table tbody tr:not('.header')").filter(function() {
return $(this).position().top + $(this).height() > mh;
});
console.log("Invisible", overflowed.length, "Jobs");
$(".job-number").html(overflowed.length);
});
Since :visible counts only items that are hidden, you can't really use it. We can .filter() on items that are in our "viewport" or not in overflow. We know the height of each element and the div. Anything greater than the height of the div, we count.

Javascript or jQuery need input field autogrow, but <td> or <div> need to be fixed

For example 2 HTML rows. The first row is header. The second row is for input. Default width for all <td> is set.
User starts to type something in input fields. As length of tex is more than default width of <td> input field starts to autogrow.
Here is my example
http://jsfiddle.net/rigaconnect/22Puw/2/
<tr>
<td width="20">1</td>
<td width="20">2</td>
</tr>
<tr>
<td width="20">
<input id="txt" type="text" onkeypress="this.style.width = ((this.value.length + 1) * 8) + 'px';" style="width:20px;">
</td>
<td width="20">
<input id="txt" type="text" onkeypress="this.style.width = ((this.value.length + 1) * 8) + 'px';" style="width:20px;">
</td>
</tr>
Problem is that <td> also autogrow.
Need that <td> always has default (fixed) width; grows only input field and as if goes over <td> on right.
Tried to set max width <td style="max-width:20px;"> no solution.
Then tried this (for header <td>)
<td style="width: 20px; display: inline-block;">1</td>
<td style="width: 20px; display: inline-block;">2</td>
but in such case they are in vertical position (not horizontal).
Here http://jsfiddle.net/rigaconnect/RURYw/10/ is example how to do it with drop down fields. Need something similar with input fields.
max-width works for me in Chrome and Firefox:
http://jsfiddle.net/22Puw/4/
td input {
max-width : 20px;
}
You can set the table to a fixed width by adding this to your CSS:
table {
table-layout:fixed;
width:60px;
}

Add a div with cordinates given in another

I want to put a div in another with cordinates given by input text fields. The added span should be with relative positions to parent's cordinates.
The problem is that it doens't add anything but yet it changes the position of the canvas.
<html>
<head>
<style>
#rectangle { position: relative; }
</style>
<body>
300 x 300 px MAX<br/>
<canvas id="rectangle" width="300" height="300"></canvas>
<br/>
<table>
<tr>
<td>Horizontal starting cordinate:</td>
<td><input type="text" id = "x" value = ""/></td>
</tr>
<tr>
<td>Vertical starting cordinate:</td>
<td><input type="text" id = "y"/></td>
</tr>
<tr>
<td>Width of the rectangle:</td>
<td><input type="text" id = "width"/></td>
</tr>
<tr>
<td>Height of the rectangle:</td>
<td><input type="text" id = "height"/></td>
</tr>
<tr>
<td></td>
<td><input type="button" id = "draw" value = "Click"/></td>
</tr>
</table>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$("#draw").click(function(e){
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var x1 = parseInt($("#x").val());
var y1 = parseInt($("#y").val());
var width = parseInt($("#width").val());
var height = parseInt($("#height").val());
$("#rectangle")
.add("div")
.css("id", "right-zone")
.css("z-index", "5")
.css("position", "absolute")
.css("left", x1)
.css("top", y2)
.css("width", width)
.css("height", height)
.css("background-color", "#FF0000")
.css("border", "solid red 1px");
});
})
</script>
Any ideas what's wrong ?
You should probably be using .append() instead of .add(). .add() will not add a div to the DOM, but an element to a set of matched elements.
Edit: on second thought, I see you are trying to append a div to a canvas element. You might be interested in checking this, where it is stated:
The contents of the canvas element, if any, are the element's fallback
content.
So you should probably replace your canvas element with a div. That, or edit your question to better reflect this detail.
There are a few "bugs" in your code, both html and JS.
Here is a working example: http://jsfiddle.net/kGd2G/1/
I.e. use div instead of canvas
<div id="rectangle" style="width: 300px; height: 300px;"></div>
To simplify JS, I used a "template div" to set some defaults for the rectangle that would be added.

Align text with a slider

I have a table structure like this
<tr>
<td>
Text to move
</td>
</tr>
<tr>
<td>
<div>jQuery slider container is in here<a>slider pointer is in here</a></div>
</td>
</tr>
When the slider moves I see the style is updated for the link element by a percentage representing how far to the right it is Ex: style="left: 11.7647%;" I want "text to move" to align itself with the slider, and also move by that percentage. Is there any way I can do this? I can add more divs/spans etc. if necessary.
Note: I know how to grab the percentage the slider has moved, the issue is just aligning it.
Since you already know the percentage, you can set the text to have a left margin of that same percentage:
$("#hoverText").css("margin-left", percent + "%");
Here's my working test code:
HTML
<table id="layoutTable" style="width:100%;">
<tr>
<td>Percent: <span id="percent"></span></td>
</tr>
<tr>
<td style="width:100%;"><span id="hoverText">Here's Some Text</span></td>
</tr>
<tr>
<td style="width:100%;"><div id="slider"></div></td>
</tr>
</table>
JavaScript
$(document).ready(function(){
$("#slider").slider({
"slide": function(event, ui) {
var percent = ui.value;
$("#percent").html(percent);
$("#hoverText").css("margin-left", percent + "%");
}
});
});

Absolutely Position DIV to the right of the last selected (by class) TD cell in a table row

I have a table like this;
<table class="std-table">
<tbody><tr>
<td>DATA</td><td>DATA</td>
</tr>
<tr class="selected-trial">
<td>DATA</td><td>DATA</td>
</tr>
<tr>
<td>DATA</td><td>DATA</td>
</tr></tbody>
I also have a div on the same level that has an image (arrow) as it's background:
<div class=selected-trial-marker></div>
The CSS is controls the basics of the marker element but what I haven't assigned is top and left values. What I'm trying to do is when the page is ready use JQuery to find out the position of the 'selected' row and position the marker element to the right of it.
This is my code thus far:
$('table.std-table tbody tr.selected-trial td:last').ready(function(){
var offset= $('table.std-table tbody tr.selected-trial').offset();
var leftOffset = $('table.std-table').width();
leftOffset += offset.left +42;
var topOffSet = (offset.top);
topOffSet = topOffSet+3;
$('.trial-selection-marker').css({'top':topOffSet+'px', 'left':leftOffset+'px'}).fadeIn('slow');
});
I'm at a loss as my offset keep coming back as null. In my CSS the table has a width of 100% within a cell that is 300px but the TD cells themselves do not have a width assigned to them (does that matter as I'm targetting the row?) Perhaps I've stared at this for too long and the answer is obvious but can anyone please help?
Many thanks in advance.
I see two issues:
jQuery doesn't like having a period in the table class name "table.std-table."
Your selector is missing a period.
var offset= $('.table-std-table tbody tr.selected-trial').offset();
<table class="table-std-table">
<tbody>
<tr>
<td>DATA</td>
<td>DATA</td>
</tr>
<tr class="selected-trial">
<td>DATA</td>
<td>DATA</td>
</tr>
<tr>
<td>DATA</td>
<td>DATA</td>
</tr>
</tbody>
</table>
<div class=.trial-selection-marker></div>
<script>
$('.table-std-table tbody tr.selected-trial td:last').ready(function(){
var offset= $('.table-std-table tbody tr.selected-trial').offset();
var leftOffset = $('tablestd-table').width();
leftOffset += offset.left +42;
var topOffSet = (offset.top);
topOffSet = topOffSet+3;
$('.trial-selection-marker').css({'top':topOffSet+'px', 'left':leftOffset+'px'}).fadeIn('slow');
});
</script>
With the help of Tom, here was the code I used in the end;
$('.std-table tbody tr.selected-trial td:last').ready(function(){
var offset= $('.std-table tbody tr.selected-trial').offset();
var topOffSet = (offset.top);
topOffSet = topOffSet-270;
$('.trial-selection-marker').css({'top':topOffSet+'px'}).fadeIn('slow');
});
I realised that the table was within a DIV that was positioned relatively so I did not have to worry about the left or right offset. CSS handled the permanent position of the marker horizontally. The script did the rest!
Thanks Tom for your help.

Categories