Sizing an <ul> in a table cell - javascript

I'm building an HTML view consisting of a <table>, with each cell containing only a single <ul> element, with a variable number of <li>. For readability reasons, my rows have a min-width: 100px;, but expand based on the contents of the <ul>. But in the other cells (which a lower number of <li>). I want my <ul> to use 100% of the cell's height. At the moment, they keep the 100px height and are verticaly centered.
My view can be summed up to that :
<table>
<tr>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
</tr>
<tr>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
</tr>
</table>
My reason for this, is that each <li> can be dragged & dropped between every <ul>, but the fact they are not resizing make dropping on an empty list kind of hazardous, because you don't "see" them, and have to guess where they are. It would be a lot easier if they were using the full cell dimensions.
I have made a lot of tries using developer tools, but could not find the right combination of CSS and Javascript.
Technicals prerequisites :
Javascript DOM manipulation is OK, I already do it to resize my table. I use ExtJS, but I'm OK with porting jQuery or pure JS code.
Compatibility with IE8 is a must (75% of final users are on IE. Gotta love the corporate world...)
Thanks for any advice !
EDIT : Here's a Fiddle that represents my code as closely as possible (NDA prevents me from sharing the original code)

For height: 100% to work as expected the container must have its height set. I have a solution below that uses JavaScript to set the height of all the ul's, it can be used as a function that runs every time it changes if needed:
function fixDimensions() {
var table = document.getElementById('table');
var trs = table.getElementsByTagName('tr');
for(var i = 0; i < trs.length; i++){
var tds = trs[i].getElementsByTagName('td');
for(var g = 0; g < tds.length; g++){
var ul = tds[g].getElementsByTagName('ul')[0];
ul.style.height = (tds[g].clientHeight - 12) + 'px';
}
}
}
The - 12 on the height is for the padding and border. JSFiddle.

You could use td themselves to draw the borders : http://jsfiddle.net/P5h8d/2/
table {
width: 100%;
background:black;
border-spacing:1px;
}
tr {
min-height: 50px;
width: 100%;
}
tbody th, tbody td {
border: 3px dotted red;
}
th, td {
width: 20%;
background:white;
}
You might not need a table if:
you use display:table instead <table> to turn <ul> visually into a cell.
DEMO
<section>
<div>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
</div>
<div>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
</div>
</section>
CSS
section {
display:table;
border-spacing:5px;
}
section > div {
display:table-row;
}
section>div>ul {
display:table-cell;
background:red;
min-width:100px;
}
you use display:flex;
DEMO
basic CSS used :
tr {
display:flex;/* reset display:defaut*/
}
td {background:gray;
display:flex;/* here again display reset */
flex-direction:column;/* make sure we draw content from top to bottom */
margin:2px;
}
ul {
padding:0;
margin:5px;;
min-width:100px;
background:red;
flex:1;/* fills or shares whole height of its flex box*/
}

Not to pollute my first answer, added here the drag and drop js
No matter the height of the ul , li drops in !
here is a CSS way to extend area around an element to increase area where it can catch mouse events.
IE8 understands :before/:after , so we use them. and set them in absolute position on top and bottom of your ul.
DEMO
the CSS used:
td {overflow:hidden;/*keep ul:pseudos inside */}
ul {
position:relative;
}
ul:before,
ul:after {
content:'';
position:absolute;
height:200px;/* whatever you need or think it is safe */
left:0;
width:100%;
}
ul:before {
bottom:100%;
}
ul:after {
top:100%;
}
added to the demo basic HTML5 drag and drop (attributes and js) since it was missing from your fiddle.
function allowDrop(ev){ev.preventDefault();}
function drag(ev){ev.dataTransfer.setData("Text",ev.target.id);}
function drop(ev){ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));}

Related

table clicked cell color scheme

I have menu in a table "mytable" like this:
<td id="1" align="center" onclick="clicked(1);"> one </td >
<td id="2" align="center" onclick="clicked(2);"> two </td >
<td id="3" align="center" onclick="clicked(3);"> three </td>
<td id="4" align="center" onclick="clicked(4);"> four </td>
...
The css:
#mytable {
background:#d0d0df;
cursor:pointer;
}
#mytable td{
background:#4092c4;
color:#efefef;
}
#mytable td:hover{
background:#e0e0e0;
color:#FF004F;
}
The javascript:
function clicked(k){
for (x=1; x<5; x++){ // reset all cells
document.getElementById(x).style.background='#4092c4';
document.getElementById(x).style.color='#efefef';
}
// set cell
document.getElementById(k).style.background='#106284';
document.getElementById(k).style.color='#FF004F';
}
How to highlight a single clicked cell and maintain the hover functionality?
The above code works, but after calling clicked() the hovering functionality is lost.
I rather not use jquery.
Syntax issue, ids that are just numbers are not valid HTML.
The problem you are having is that when the javascript runs, it appends the styles inline on the elements, and the CSS styles cannot override inline (not without adding things like !important, and that just gets ugly).
I would steer away from writing styling in the JS, just use it to change classes. So make a new class, lets call it .active, and when you click a tablecell just add the class, and remove the class from all the others.
Something like (this is example only, some tweaking may be required)
function clicked(k){
var otherCell, thisCell;
for (x=1; x<5; x++){ // reset all cells
otherCell = document.getElementById(x);
otherCell.className = otherCell.className.replace('active','');
}
// set cell as active
thisCell = document.getElementById(k);
thisCell.className += thisCell.className + ' active';
}
and then set the styles only in css, something like
#mytable {
background:#d0d0df;
cursor:pointer;
}
#mytable td{
background:#4092c4;
color:#efefef;
}
#mytable td.active{
background:#106284;
color:#efefef;
}
#mytable td:hover{
background:#e0e0e0;
color:#FF004F;
}
This way you have more control over the 'cascading' of the style rules, being more specific or changing the order of the rules will give you possible different outcomes.
As per fiddle here
This is probably overkill, but the jQuery javascript library makes this trivial.
I've channged the HTML too becuase using table for non-tabula data should be avoided.
New HTML:
<ul id="mytable">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</ul>
Also note, no ID's on the items and no in-line javascript, nice and clean.
New CSS:
#mytable {
background:#d0d0df;
cursor:pointer;
list-style:none;
padding-left:0;
}
#mytable li {
background:#4092c4;
color:#efefef;
display:inline-block;
margin:2px -2px 2px 2px;
padding:3px;
}
#mytable li:hover {
background:#e0e0e0;
color:#FF004F;
}
#mytable li.active {
background:#106284;
color:#efefef;
}
Note: I've used inline-block for the list items to orientate the horizontaly, you could also use float or table-cell. This is a good article on floats vs inline-blocl. Also note the new active class.
Now for the super-simple jquery (make sure to include the jquery library!)
$(document).ready(function(){ //Performs the following code when the document is fully loaded
//Assigns a click event handler to list items in an element with ID "myTable"
$("#mytable li").click(function () {
//Remove the active class from list items in #mytable that were not clicked
$("#mytable li").not($(this)).removeClass("active");
//Add the active class to the clicked element.
$(this).addClass("active");
});
});
Fiddle
Just make sure to include the jquery library and to use $(document).ready();
Handy jQuery Links
Document Ready
Selectors
Click
Not
Add Class
Remove Class

Why the tool-tip pop-up is not appearing when I apply the same logic which is working fine in other fiddle?

The non-working fiddle is as follows in which I'm not getting the tool-tip pop-up appear. Also the text to be wrapped inside a tool-tip pop-up is also not hidden:
http://jsfiddle.net/Dq3X7/1/
The working fiddle is as follows in which I'm able to show the tool-tip pop-up on the click of a text contained in . Also the text to be wrapped inside a tool-tip pop-up is also hidden:
http://jsfiddle.net/Q3LXR/11/
The HTML code is as follows:
<table class="base-table selection-table" width="100%" border="0" cellspacing="0" cellpadding="0" style="margin-top:15px;">
<tr class="evenRow" id="37261">
<td class="question">
<ul class="tabl-head">
<li>Question 1.</li>
<li class="center-align"><span>Report question issue - QUE37261</span>
<ul class="tooltipText">
<li class='info'>Some text to fill the box with.</li>
</ul></li>
</ul>
<ul class="options w-auto">
<li><strong>Question:</strong>
Pair of contrasting characters controlling the same trait is called:
</li>
<li><strong>Answer:</strong>
<p>
<b style="font-size:13px;">1.</b>
Factors
<br />
</p>
<p>
<b style="font-size:13px;">2.</b>
alleles
<br />
</p>
<p>
<b style="font-size:13px;">3.</b>
alloloci
<br />
</p>
<p>
<b style="font-size:13px;">4.</b>
paramorphs
<br />
</p>
</li>
<li><strong>Correct Answer Option : 2</strong></li>
</ul>
</td>
</tr>
</table>
The Javascript of my non-working fiddle(1st one) is as follows:
"use strict";
function click(event) {
var elem = this.parentNode.querySelector('.info_container');
if (elem)
elem.style.display = elem.style.display === 'block' ? 'none' : 'block';
}
function toolify() {
console.log("toolfiy",arguments)
var idx,
len,
elem,
info,
text,
elements = document.querySelectorAll('li.tooltip'),
canvas,
imgurl,
pointer,
tipHeight = 20,
tipWidth = 20,
width = 200,
height = 100,
ctx;
// Create a canvas element where the triangle will be drawn
canvas = document.createElement('canvas');
canvas.width = tipHeight;
canvas.height = tipWidth;
ctx = canvas.getContext('2d');
ctx.strokeStyle = '#000'; // Border color
ctx.fillStyle = '#fff'; // background color
ctx.lineWidth = 1;
ctx.translate(-0.5, -0.5); // Move half pixel to make sharp lines
ctx.beginPath();
ctx.moveTo(1, canvas.height); // lower left corner
The CSS code for first fiddle is as follows:
li{
display:block;
}
li.tooltip
{
position:relative;
display:inline-block;
cursor:pointer;
width:300px;
text-align:right;
}
li.tooltip > ul li.info
{
display:none;
}
li.tooltip > ul li.info_container
{
position:absolute;
right:20px;
width:200px;
height:100px;
display:none;
color:#000;
}
li.tooltip ul li.info
{
text-align:left;
position:absolute;
left:1px;
right:1px;
top:20px;
bottom:1px;
color:#000;
padding:5px;
overflow:auto;
border:1px solid #000;
}
The first fiddle should also work as of second fiddle. That is the tool-tip popup shpuld get appear when user clicks on the text Report question issue - QUE37261 and also the text to be displayed within a tool tip(i.e. the text "Some text to fill the box with.") should not be displayed initially.
Other similar <li>s are also present on the webpage but for your understanding I've put only one entry here. It should work for every entry once it starts working for single entry.
I've applied the same logic as of second fiddle to first one but it's not working. Can anyone help me in this regard please?
Some reasons and solutions to your question.
1) You've used no wrap - in <head> for your working fiddle but onLoad for your non-working fiddle. The difference between this two is:
onLoad: wrap the code so it will run in onLoad window event
no wrap - in <head>: do not wrap the JavaScript code, place it in section
In your case, you need to use no wrap - in <head>
2) You need to add class tooltip to the parent li of your .info li
<li class="center-align tooltip"><span>Report question issue - QUE37261</span>
3) Add background-color: #fff; to your .info li to make it cover the content behind it.
Updated Fiddle

Issue with jquery remove method on IE7?

<table class="myCustomers">
<tbody>
<tr>
<td>
<ul id="salesCustomers">
<li title="cust 1"><a id="cust_1" >customer 1</a></li>
<li title="cust 2"></li>
</ul>
</td>
</tr>
</tbody>
when i do on below on IE 7, DOM element corresponding to "customer 1" gets removed from container "salesCustomers" but
"salesCustomers" container does get adjusted(i mean IE 7 displays empty space in place of it) after removal of element
$('#cust_1').remove();
It works fine on IE8,9,firefox,chrome but not on IE 7?
Updated:-
CSS part is
table.myCustomers li {
margin: 8px;
}
table.myCustomers li a {
text-decoration: none;
}
a {
color: #000000;
margin: 3px;
}
This code
$('#cust_1').remove();
will only remove the tag <a id='cust1'>customer1</a> tag. Its surrounding <li> tag is still in the DOM. If your CSS has assigned some height to <li> elements, it will still appear as an empty space.
The empty space may be since the li is still there. (as pointed out by Jayraj)
If you want to remove the li corresponding to the #cust_1 as well,
You have a couple of ways to do it,
$("[title='cust 1']").remove();
$("#cust_1").parents("li").remove(); //this will remove the
child element as well
Test link

Repurposing some Javascript for a similar DOM element

On my page I have an unordered list with some list items that serve as links to load content into a div.
The art direction requires that the list items be fully justified to the left and right. I've written some JavaScript to figure out how wide the ul is and calculate the width of the individual li elements, divide the remaining space and push the elements to the left and right respectively. It works great.
Now we want to add another ul under the first with another set of links.
How can I repurpose my code to do the same work as before?
All the list items are styled display:inline; and they need to be fluid in width in the event a font on one browser is a little bigger than another.
Here's my HTML: (It's all run together to overcome the spacing issue with inline list elements)
<div id="portfolio">
<ul class="stacked-nav-top">
<li class="project_link">
<a href="#" class="project_class planning" id="commercial-industrial" title="Commercial Industrial Projects">
Commercial & Industrial
</a>
</li>
<li class="breaker">//</li>
<li class="project_link">
<a href="#" class="project_class planning" id="government-institutional" title="Government Institutional Projects">
Government & Institutional
</a>
</li>
<li class="breaker">//</li>
<li class="project_link">
<a href="#" class="project_class planning" id="affordable-housing" title="Affordable Housing Projects">
Affordable Housing
</a>
</li>
<li class="breaker">//</li>
<li class="project_link">
<a href="#" class="project_class planning" id="multi-family-housing" title="Multi-family Housing Projects">
Multi-family Housing
</a>
</li>
</ul>
</div>
And my JavaScript:
$(function()
{
var linkwidth = 0;
$('#portfolio ul li.project_link').each(function()
{
linkwidth += $(this).outerWidth()
});
var leftover = ($('#portfolio ul').outerWidth() - linkwidth);
var breakerwidth = Math.floor((leftover / 3));
$('#portfolio ul li.breaker').css('width', breakerwidth);
});
EDIT
My CSS:
section#portfolio ul {
display:block;
width:820px;
text-align:center;
}
.stacked-nav-top {
border-top:solid 1px rgba(97,58,17,.3);
margin:0px;
background:transparent url(images/dotted_line_820.png) center 19px no-repeat;
padding:10px 0px;
}
.stacked-nav-bottom {
border-bottom:solid 1px rgba(97,58,17,.3);
padding-bottom:10px;
margin:10px 0px 15px 0px;
}
section#portfolio ul li {
display:inline;
font:lighter .65em "Tahoma", "Geneva", sans-serif;
color:rgb(145,145,145);
text-transform:uppercase;
}
section#portfolio ul li.breaker {
display:inline-block;
text-align:center;
}
I've tried wrapping all the JavaScript in a $('#portfolio ul').each(... but that doesn't seem to work. It sets the spacing according to the first ul not both individually.
I'm not really sure to understand what do you want but,
if you want to repeat the operation on each ul of your section, you have to loop on each ul, then do your calculations.
Demo here, respecting your HTML inline syntax (inline-block problem).
http://jsfiddle.net/ggX2r/2/
// Inside a document.ready scope of couse...
$('#portfolio ul').each(function () {
var linkwidth = 0,
leftover,
breakerwidth;
// *this* refers to your current <ul> child of your #portfolio.
$('li.project_link', this).each(function() {
// *this* refers now to your current <li.project_link> element
linkwidth += $(this).outerWidth();
});
leftover = ($('#portfolio ul').outerWidth() - linkwidth);
breakerwidth = Math.floor((leftover / 3));
$('li.breaker', this).css('width', breakerwidth);
});

Make HTML Table height equal to the middle TD elements height

I have a HTML table with 1 row. In that row there are 3 cells(td elements). The centre cell contains p elements & all the main content of the page. The left & right td elements contain an img element; they are images of the left & right sides blue column.
My Problem: I am trying to make the height of the table be equal to the height of the centre td element only. And the left & right images will scale up & down according to the dimensions(height) of the centre td element. But right now, the table is always 1200px in height & thats because the left & right images are 1200px in height.
I hope this makes sense & that you understand what I am attempting to do :P So I am tryinging to make the table height equal to the height of the centre td cell only.
Is there a way to do this in pure HTML & CSS. If not javascript will do it wont it?
.contentTable { height: inherit; }
.tableTopPanel { height: 6.25%; }
.tableBottomPanel { height: 6.25%; }
.tableLeftPanel { width: 6.25%; padding: 0; margin: 0; }
.tableRightPanel { width: 6.25%; padding: 0; margin: 0; }
.tableCentrePanel { background-color: #FFFFFF; }
.pageContent { border-color: #99CCFF; border-width:thin; border-style:solid; border-right-width:thick;
border-bottom-width:thick; padding-top: 0.5em; border-top: 0; }
<table class="contentTable" id="test">
<tr>
<td class="tableLeftPanel"><img src="../Images/contentLeftBk.png" alt=""/></td>
<td class="tableCentrePanel">
<img class="pageHeading" src="Images/coursesHeading2.png" width="100%" alt=""/>
<div class="pageContent" id="coursesContent">
<p>Kazcare cooperates with WEA Illawarra to offer a range of educational courses.</p>
<p>Some of the courses held at Kazcare Education Facilities include: </p>
<ul class="leftCol">
<li>Front Line Management Courses</li>
<li>Cert 4 Training & Assessment</li>
<li>Environment Courses</li>
<li>Music Appreciation</li>
<li>Craft Classes</li>
<li>Candle Making</li>
</ul>
<ul class="rightCol">
<li>Art Classes</li>
<li>Drawing Classes</li>
<li>Yoga</li>
<li>Dancing</li>
<li>Exercise Classes</li>
<li>Art History Classes</li>
</ul>
<br/>
<p class="a">
To view the full range of WEA Illawarra courses held at KazCare please visit WEA Illawarra Courses.
</p>
</div>
</td>
<td class="tableRightPanel"><img src="../Images/contentRightBk.png" alt=""/></td>
</tr>
</table>
If I were implementing a layout like this, I would likely rely on pure CSS instead of using a table. There are numerous examples of three column layouts online, here's one example:
http://www.manisheriar.com/holygrail/index.htm
If you want to use the table, I suppose it depends on what the contents of your images look like - should they be vertically tiled if the page gets too long? Does it need to be a certain width? There are a few options here, but having an idea of what you're trying to build would help. Here are a few options:
Use the background-image property of CSS - http://www.w3schools.com/cssref/pr_background-image.asp
Set a fixed width on the outer TD elements, and set overflow to hidden: http://www.w3schools.com/cssref/pr_pos_overflow.asp
Hope this helps, happy coding!

Categories