Dynamic Table Width - javascript

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();
});

Related

jQuery UI Draggable: Get drag offset of A LOT of dynamically created elements

I'm creating a <table> element in the DOM and using javascript to dynamically append many cells to it. For the sake of explanation let's say I create 10 rows with 10 fields per row. I'm using simple counters to assign unique IDs for the div containers inside of those fields. Easy enough. This is what I get:
<table>
<tr><td><div id="field0"><div id="handle0"></div></div></td></tr>
.....
<tr><td><div id="field99></div id="handle99"></div></div></td></tr>
</table>
Note that the numbers 0-99 are what is dynamically appended to each element ID.
I now want to go ahead and attach the jQueryUI .draggable function to each handle and retrieve the coordinates of each handle relative to each surrounding parent div like so:
for (var counter = 0; counter < 100; counter++) {
var dragHandle = $('#handle' + counter);
var dragField = $('#field' + counter);
dragHandle.draggable({
containment: dragField,
scroll: false,
drag: function () {
var offset = $(this).offset();
var xPos = (offset.left) - $(this).offsetParent().offset().left;
var yPos = (offset.top) - $(this).offsetParent().offset().top;
console.log(xPos);
console.log(yPos); // These add up?!
}
});
}
Now, the functions work, the table gets properly initialized and all of the individual handles in the table are now draggable.
The problem is that the xPos and yPos values that are returned by the above function are not the correct coordinates relative to each field but instead they add up.
I feel like I'm missing something terribly obvious and would really appreciate if someone could help.
Edit: The example above uses console.log for simplification. My original script performs more complex computations in the on drag event. I won't be able to use a class selector to go through all of the elements like someone suggested in the comments because I need to retrieve unique offset and position values for each unique handle ID relative to its unique containment ID.
var xPos=(offset.left)-$(this).position( ).left
var yPos=(offset.top)-$(this).position( ).top
Instead of offsetParent you can modify.
var xPos = (offset.left) - $(this).parent().offset().left;
var yPos = (offset.top) - $(this).parent().offset().top;

Aligning columns from different tables

Let's say I have two tables with some text in between:
<table>
<tr><td>A</td><td>0000</td><td>Some text goes here...</td></tr>
<tr><td>B</td><td>11</td><td>... and here</td></tr>
</table>
Some text goes here.
<table>
<tr><td>CCC</td><td>1</td><td>Some text goes here...</td></tr>
<tr><td>DDD</td><td>0</td><td>... and here</td></tr>
</table>
Is is possible to make these two tables having the same column width?
That is I want the first column of table 1 to be 3 characters (e.g. CCC) big ; and I want the second column of table 2 to be 4 characters (e.g. 0000) big.
Please note that I don't know what the width of each column should be, therefor I don't want to define it beforehand in a CSS file.
I'm more interested in a dynamic approach using Javascript.
The different steps would be something like :
Build the two tables;
Get the maximum width of columns 1 and 2;
Update the CSS properties of my tables using these values.
(put ids on your table)
You can use jQuery selectors to get all your width values of your tds like :
var maxWidth = 0;
$("#table1 td").each(function() {
var width = $(this).css("width");
if(width > maxWidth) maxWidth = width;
});
And then
$("#table1 td").css("width", width);
Using JQuery you could do the following:
$(document).ready(function() {
var tdWidth = 0;
$('td').each(function() {
width = $(this).width();
if(width > tdWidth) tdWidth = width;
});
$('td').css("width", tdWidth);
});

Trying to Set the Index of a td in jQuery

In the process of creating a tile-swap puzzle game for my jQuery class. Right now I'm working on trying to make the clicked tile switch with the blank tile (I'll figure out how to limit it to adjacent tiles afterwards). I've stored indexes of both indexes in new variables, but I can't figure out how to assign a variable as the td elements index.
$(document).ready(function(){
$('img').click(function(){
var tileSelected = $(this); //grab the clicked tiles index
var tileIndexOld = $("img").index(tileSelected);
var blankTile = $("#blank"); //grab the blank tiles index
var blankIndexOld = $("img").index(blankTile);
var tileIndexNew = blankIndexOld; //swap tile and blank indexes
var blankIndexNew = tileIndexOld;
$(this).attr("index", tileIndexNew);
$("#blank").attr("index", blankIndexNew);
});
});
I've also tried doing things like $(tileSelected).index(tileIndexNew); and $(this).index() = tileIndexNew; etc. I just can't seem to figure out how to overwrite with the new index.
Edit:
Okay, I've been shown the wickedness of my (attempted) index swapping ways! Still working on the solution, but I'm changing tracks and focusing on altering the src's as suggested by Starscream1984. I'll update again once I've got it figured out, many thanks to all!
Solution:
After trying it three different ways (with multiple sub-variations) this is what I ended up with:
$(document).ready(function(){
$("td").click( function(){
var tileVertical = $(this).index(); //get clicked tiles vertical position via its td
var tileHorizontal = $(this).parent().index(); //get clicked tiles horizontal position via its tr
var blankTile = $("#blank").parent(); //getting the td that contains the blank tile
var blankVertical = blankTile.index(); //get blank tiles vertical position (via its td)
var blankHorizontal = blankTile.parent().index(); //get blank tiles horizontal position via its tr
if( Math.abs(blankVertical - tileVertical) + Math.abs(blankHorizontal - tileHorizontal) == 1) //check if clicked tile is adjacent to the blank tile
{
blankTile.empty().html( $(this).html() ); //put the tile html into the blank slot
$(this).html("<img id='blank' src='blank.jpeg' width='200px' />"); //fill the tile slot with the blank, ID IS CRITICAL!!!!
} //function will only run once if id is omitted from this tag!!!
return 1;
});
});
My original approach tried to use the index as a quick and dirty variable to swap out. What I discovered was that the index in this case is simply more like a map with x and y coordinates. It was the inner html of the table cell that needed to be swapped, not the index itself.
You need to move the elements around using jQuery DOM modification methods. This solution assumes that each tile is contained in a DIV in the grid.
$('img').click(function(){
var tileSelected = $(this);
var parentSelected = tileSelected.parent();
var blankTile = $("#blank");
var blankParent = blankTile.parent();
parentSelected.append(blankTile);
blankParent.append(tileSelected);
});
A)
$('img').each(function(index, elem){
console.log(index);
});
B)
$('img').click(function(){
var index = $(this).index();
//or
//var index = $('img').index($(this));
console.log(index);
});
Are the right ways. So your code seems to be correct. Are you sure that all imgages exists at the moment you run the function? Do you noticed that your selector find all img in DOM?
If you want to assign an index variable for the td, one approach to do it dinamically is the following:
$(document).ready(function(){
var tdArray = $("td");//grabs all td elements
for(i = 0; i < tdArray.length; i++){
$(tdArray[i]).attr('data-index',i);//adds a data-index attribute on each one
}
});
You could then handle a click event like this:
$("td").click(function(){
alert($(this).attr('data-index'));
});
To keep track of your blank tile, you could simple assign its data-index to a global variable.

Get next table cell vertically in table with rowspans

I need to find index of cell in table below a given cell. Imagine that I don't know anything about td_end, I just click at td_start and need to find td_end. Example (need find index of red cell(td_end), knowing index of green cell (td_start)): http://jsfiddle.net/r5BDW/65/
Problem that table will contain a lot of cells with rowspan attr, so usual searching by equal index will not work. Any advice how to find such cells?
example table:
<table border="1" style="width: 100%;">
<tr><td>111</td><td rowspan="3">22</td><td>3</td></tr>
<tr><td>111</td><td>3</td></tr>
<tr><td>111</td><td class="td_start">3</td></tr>
<tr><td>111</td><td>22</td><td class="td_end">3</td></tr>
<tr><td>111</td><td>22</td><td>3</td></tr>
<tr><td>111</td><td >22</td><td>3</td></tr>
</table>
console.log($('.td_start').index() ) // =1
console.log($('.td_end').index() ) // =2
I think that would be almost a crazy act to guess all the possible colspan and rowspan combinations.
What I would try with, is to literally
"touch" the element that is visually beneath the selector element using elementFromPoint
jsFiddle demo
$.fn.nextVert = function(){
var b = this[0].getBoundingClientRect();
var nxtV = document.elementFromPoint(b.left, b.bottom+10);
if(nxtV.tagName==="TD") return $(nxtV);
};
$('.td_start').nextVert().text("hello");
console.log( $('.td_start').nextVert().index() ); // 2
by simply getting the elementFromPoint
starting from the this bottom value + some tiny offset (I used 10px)
chek this solution: http://jsfiddle.net/r5BDW/68/
find td with same left position
jQuery
$(document).ready(function() {
var $td2=$('.td_start2');
fidnBelow($td2);
var $td=$('.td_start');
fidnBelow($td);
});
function fidnBelow($td)
{
var rez='';
var p=$td.position();
var left=p.left;
var td_count=$('tr').size();
var ind_tr=$td.parent().index();
var $table=$('#table');
ind_tr++;
for(i=ind_tr;i<td_count;i++)
{
var $below_tr=$table.find('tr').eq(i)
$below_tr.find('td').each(function(){
var tp=$(this).position();
var tleft=tp.left;
if(left==tp.left) rez=$(this).html();
})
if(rez!='') break;
}
alert(rez);
}

How to find width of inner elements

I couldn't find any other questions asking the same thing, though that may be a problem with my search phrasing.
I'm trying to figure out how to find the largest width of all elements contained inside of a container div with a fixed width. So, in the image below, the black box is the container div with a fixed width. The red box represents the contents of the container div, which are subject to change. I want to find the width of the red box, using only the black box in js.
Here is a jsfiddle with what I've been working on/trying:
http://jsfiddle.net/w87k5/1/
the current jquery functions I've tried, with no success:
.width();
.innerWidth();
.outerWidth();
.scrollLeft();
Note: I do not know ANYTHING about the contents of this container. They could be any html element or mix of html elements, from divs to imgs to iframes. I could put a "red box" without a fixed width surrounding them. Overflow of the black box will be hidden.
Update: There could be any number of children in the container. Like this: http://jsfiddle.net/w87k5/3/
Update 2: I'm going to run benchmark speed tests on all of the answers to see which one is the fastest, and select one after that. Thanks for all your input!
Benchmarks:
I generated 1000 divs with a random width of inbetween 0 and 100, recorded the Date().getTime(), did the test, then recorded time again. Here are the results:
~2418 avg. milliseconds with the for loop for length. I might have messed this one up somehow?
for (var i = 1; i <= count; i++){
var q = $("#box :nth-child(" + i + ")").width();
if(q > box){
box = q;
}
}
~34.4 avg. ms for the .each loop.
~22.4 avg. ms for the .map function. (Chosen answer.)
If you need all nested elements can search with * selector which will return all descendent elements:
var widthArray=$('#box *').map(function(){
return $(this).outerWidth();
}).get();
var maxWIdth= Math.max.apply(Math, widthArray);
For just children:
var widthArray=$('#box').children().map(function(){....
You could use .each() to cycle though each child element.
jsFiddle example
var widths = [];
$('#box').children().each(function(i){
widths[i] = $(this).width();
});
alert(Math.max.apply(Math, widths));
Which will return the width of the child element with the largest width.
Get the number of children, and loop through to get the width of each
$(document).ready(function () {
var count = $("#box").children().length;
var h = 0;
for (var i = 1; i <= count; i++) {
max = $("#box :nth-child(" + i + ")").width();
var h = Math.max(max, h);
}
alert(h);
});
http://jsfiddle.net/JDVN3/1/
Please not that the index starts from 1 and not 0.
Check out: http://api.jquery.com/nth-child-selector/

Categories