Long text visualization on table headers - javascript

I'm trying to make some html with css pages (I'm new to both) and I want to add styles to a table header with column long names, this names are required to be long, but the column width is fixed, making these columns without css would show them with text wrapping so the row height would show just NOT nice. I'm trying to find a nice way to display the table. What comes to my mind, is "cut" the name of the column veryLongColumName to veryLong... and on hover of the table header, display it as they are originally, how can I do this? do I need to begin learning JavaScript >> jQuery in order to do this? Any sample code I can use?
If you have a better idea about how to display nicely that content it is welcome.
I have no idea how to do this as it seems that there need to be data manipulation (so I need JavaScript or jQuery); how ever, I think that having two div tags with the shortened name and the original name in another and display one or other depending on the mouse hover will do the work but I don't know how to make that happen (is this also jQuery?).
Thanks in advance.
http://jsfiddle.net/byakku/Q5V98/1/

I tried to implement it in plain javascript without any lib/plugin and below is what I have,
Solution using plain javascript (without jQuery) DEMO
The above demo code can be reduced a lot by using jQuery,
Solution using jQuery - DEMO
Using jQuery:
function shortHandTableHeaders(tableID, limit) {
var ths = $('#' + tableID + ' thead tr th');
var content;
ths.each (function () {
var $this = $(this);
content = $this.text();
if (content.length > limit) {
$this.data('longheader', content);
$this.text (shortHandHeaderTxt(content, limit));
$this.hover (
function() {
$(this).text($this.data('longheader'));
},
function () {
$(this).text(shortHandHeaderTxt($this.data('longheader'), limit));
}
);
}
});
}
function shortHandHeaderTxt(txt, limit) {
return txt.substring(0, limit - 3) + "...";
}
Below is the another implementation without jQuery,
function shortHandTableHeaders(tableID, limit) {
var tableEl = document.getElementById(tableID);
var thead = tableEl.getElementsByTagName("thead");
var thtrs = thead[0].getElementsByTagName("tr");
var ths, content;
for (var i = 0; i < thtrs.length; i++) {
ths = thtrs[i].getElementsByTagName("th");
for (var j = 0; j < ths.length; j++) {
content = ths[j].innerHTML;
if (content.length > limit) {
ths[j].title = content;
ths[j].innerHTML = shortHandHeaderTxt(content, limit);
addEventHandler(ths[j], 'mouseover', function() {
this.innerHTML = this.title;
});
addEventHandler(ths[j], 'mouseout', function() {
this.innerHTML = shortHandHeaderTxt(this.title, limit);
});
}
}
}
}
function addEventHandler(el, eType, handler) {
if (el.addEventListener) { // W3C, FF
el.addEventListener(eType, handler, false);
} else if (el.attachEvent) { // IE
el.attachEvent('on' + eType, function() {
handler.call(el);
});
}
}
function shortHandHeaderTxt(txt, limit) {
return txt.substring(0, limit - 3) + "...";
}

Here's a way to do it with just CSS.
demo
In the HTML, put a class="short" on the abbreviated message.
<table>
<thead>
<th>Veeery long text title for a column header</th>
<th class="short">Veeery long...</th>
</thead>
<tbody>
<tr>
<td>What it looks like when mouse hover</td>
<td>What it looks like when mouse is out of header, height should fit the content</td>
</tr>
</tbody>
</table>
Our CSS overloads the display property. There are much nicer ways to do this, but they aren't compatible with most IE versions. I haven't tested this on more than FireFox, but it should work for IE7+, and modern browsers.
thead th {
display: none;
}
thead th.short {
display: table-cell;
}
thead:hover th {
display: table-cell;
}
thead:hover th.short {
display: none;
}

Related

How would I be able to target a specific table to manipulate it?

Html page
Browser view of html page:
CSS page
I'm trying to target a specific table when I click the buttons. But the function I have set up effects all of them, even the table in the middle. I figured table.children[0].childElementCount > 10 would only effect the first and the third table since there the one that have more then 10 rows. Would any one know how I can target an individual table that has a more then 10 rows?
Please let me know if my question makes sense and if I need to provide additional information.
Javascript
/* ==========================================================================
ShowDebug constructor
========================================================================== */
var ShowDebug = function () {
this.tables = document.querySelectorAll('.tbl_List');
this.counters = {
min: 1,
max: 5
}
this.rule = document.styleSheets[0].rules[0]
this.appendElements();
}
/* ==========================================================================
ShowDebug Inherited methods
========================================================================== */
ShowDebug.prototype = {
// Create button to collopase table items
createLessBtn() {
var lessBtn = document.createElement("button");
lessBtn.className = "btn";
lessBtn.textContent = "Less";
lessBtn.setAttribute("onclick", "showDebug.showLess();");
return lessBtn
},
// Create button to expand table items
createMoreBtn() {
var moreBtn = document.createElement("button");
moreBtn.className = "btn";
moreBtn.textContent = "More";
moreBtn.setAttribute("onclick", "showDebug.showMore();");
return moreBtn
},
// Append elements to the tables
appendElements() {
console.log(document.styleSheets[0].rules[0])
this.tables.forEach(function (table) {
if (table.children[0].childElementCount > 10) {
let itemCounter = document.createElement('span')
itemCounter.className = "item-counter"
itemCounter.innerHTML = ` 1 - 10 of ${table.children[0].childElementCount} items`
table.children[0].appendChild(itemCounter);
table.children[0].appendChild(this.createLessBtn());
table.children[0].appendChild(this.createMoreBtn());
}
}, this)
},
// Collaspe table items
showLess() {
this.tables.forEach(function (table, index) {
if (table.children[0].childElementCount > 10) {
if (index === 0) {
console.log("less");
showDebug.counters.max = showDebug.counters.max - 5;
showDebug.rule.selectorText = "table tr:nth-of-type(" + showDebug.counters.min + "n+" + showDebug.counters.max + ")";
}
}
})
},
// Expand table items
showMore() {
this.tables.forEach(function (table, index) {
if (table.children[0].childElementCount > 10) {
if (index === 0) {
console.log("more");
showDebug.counters.max = showDebug.counters.max + 5;
showDebug.rule.selectorText = "table tr:nth-of-type(" + showDebug.counters.min + "n+" + showDebug.counters.max + ")";
}
}
})
}
}
var showDebug = new ShowDebug();
CSS
table tr:nth-of-type(1n+5) {
display: none;
}
table {
width: 100%;
}
/* .hide:nth-of-type(1n+1) {
display: none;
background: red;
} */
.querySelectorAll() will create a collection (as you know). But since you are selecting a table using its id attribute, there will only be one. HTML id attributes must be unique on the page. Therefore, .querySelector() is the correct solution.
Change:
document.querySelectorAll('#tbl_List');
To
document.querySelector('#tbl_List');
Then, refactor to remove the forEach() loops. There will only be one table rather than a NodeList.
Edit
You should be aware that there are several ways to collect all the tables. You can use document.querySelectorAll('table') and that will return a collection of all tables. (you don't need id's or class names just for selection).
Based upon your comment below: Please investigate event delegation:
https://davidwalsh.name/event-delegate
Given a table:
<table>
<thead>
<tr><th></th><th></th></tr>
<thead>
<tbody> /** <-- BIND YOUR CLICK HANDLER HERE !!!! **/
<tr><td></td><td><button>Less</button><button>More</button></td></tr>
<tr><td></td><td><button>Less</button><button>More</button></td></tr>
<tr><td></td><td><button>Less</button><button>More</button></td></tr>
<tr><td></td><td><button>Less</button><button>More</button></td></tr>
</tbody>
</table>
Notice where to bind the click handler. Binding it there allows you to retrieve the cell, row or entire table body no matter what cell the button is in that gets clicked. Hope that makes sense.

Table column styling with jquery

I have a table on my website and i am trying to style it with jquery. the code i am using works fine with normal table but if in a column two cells are merged it destroys the style. I want 1 column to be coloured and one column blank
jquery code
$( document ).ready(function() {
$('#tab-table').find("table").addClass('s-table');
$(".s-table tr td:nth-child(2n+1)").css("background-color","#d1deec");
});
link to fiddle
CSS can help you to draw colonnes background-colors if you use proper markup :
<colgroup>
<col/>
<col/>
</colgroup>
and then basicly apply :
col {background:#789 url(image.png);}
A mixed of background in col , and rgba colors in cells can give you this : http://codepen.io/gc-nomade/pen/ybDhH/
Else , if you do not have hands on markup, trick it and do it from headers cells.
You could use some tricks with box-shadow or pseudo-element from header cells and overflow on table.
Pseudo-element technic :
http://codepen.io/gc-nomade/pen/dDwmf
and box-shadow technic: http://codepen.io/gc-nomade/pen/xqALu
I'd use a loop (if the merged cells will always stay the same..
see fiddle:
http://jsfiddle.net/jFIT/k5yZ9/4/
$("table tr:not(:first)").each(function() {
if($(this).find('td').length == 7)
{
//can replace with array 2/4/6
$(this).find('td:nth-child(2)').css("background-color","#d1deec");
}
else
{
// 3/5/7
$(this).find('td:nth-child(3)').css("background-color","#d1deec");
}
//loop array
});
Update
http://jsfiddle.net/jFIT/k5yZ9/6/
Using array:
$("table tr:not(:first)").each(function () {
var arr = [];
var $this = $(this);
if ($(this).find('td').length == 7) {
arr.push(2, 4, 6);
} else {
arr.push(3, 5, 7);
}
$.each(arr, function (ind, val) {
$this.find('td:nth-child(' + val + ')').css("background-color", "#d1deec");
});
});

Change color of a CSS when mouse hover an TD

I'm developing an site with a large table (18 row x 11 columns). To make it easier for who is looking that table, I made it hover an different color for the TR with that:
.responsive tr:hover {
background-color: red;
}
But I want to make the same with the column. But if I use .responsive td:hover {background-color: blue;}, it just hovers the single TD, not the entire column. At least, every TD has the class col1, col2, etc.
How is it possible to change a CSS property when hovering the TD. If this is possible, I can change the background-color from class col1 when I hover the col1 TD.
Any idea?
There is no concept of column in HTML or CSS.
You must use javascript to do that.
Here's a solution using jQuery :
var clean = function(){
$('td').removeClass('colHover');
}
$('td').hover(
function() {
clean();
$('td:nth-child('+($(this).index()+1)+')').addClass('colHover');
}, clean
);
Demonstration
Now, mainly for fun, if you want to handle colspan, you could do that :
var clean = function(){
$('td').removeClass('colHover');
}
$('td').hover(
function() {
clean();
var col = 0;
$(this).prevAll().each(function(){col += parseInt($(this).attr('colspan')||'1')});
$('tr').each(function(){
var c = 0, done = false;
$('td',this).each(function(){
if (c>col && !done) {
$(this).prev().addClass('colHover');
done = true;
}
c += parseInt($(this).attr('colspan')||'1');
});
if (!done) $(this).find('td:last-child').addClass('colHover');
});
}, clean
);
Demonstration

change backround image of another div when hovering over list item

I have a list in a div and I would like to change the background image of the parent div (#homepage_container) when I hover over a list item.
here's the site:-
http://www.thebalancedbody.ca/
Is this possible? I'm guessing I'll have to use javascript.
Thanks
Jonathan
This is quite simple with pure javascript.
function changeBg(newBg)
{
var imgdiv = document.getElementById("divwithbackground");
imgdiv.style.backgroundImage = "url(" + newBg + ")";
}
Or using sprites:
imgdiv.style.backgroundPosition = "new position";
This can be executed on mouseover for any of your li's. Event registration in javascript can be done many ways, but to do it in script, I recommend QuirksMode's method here.
Something like:
function addEventSimple(obj,evt,fn) {
if (obj.addEventListener)
obj.addEventListener(evt,fn,false);
else if (obj.attachEvent)
obj.attachEvent('on'+evt,fn);
}
And on load:
// get the list items
var ul = document.getElementById("ulId");
var lis = ul.getElementsByTagName("li");
// add event handlers
for (var i = 0; i < lis.length; i++)
{
addEventSimple(lis[i], "mouseover", (function(j) {
return function() {
// get your background image from the li somehow
changeBg(lis[j].id + "_bg.png");
};
})(i)); // use a closure to capture the current value of "i"
}
You have to use JS.
Better to learn something like jQuery.
With it you will have to do something like
var images = ['img1.jpg', 'img2.jpg', ...]
for (var i = 0; i < li_count; ++i) // li_count is the number of li's
$('li:eq(' + i + ')').mouseover(function() {$('#homepage_container').css('background-image', images[i]})
Anyway, if you wish to use such kinds of techniques, you have to learn JS.
See http://www.w3schools.com/js/default.asp and for basics and http://docs.jquery.com/Tutorials for jQuery.
I suggest installing the Jquery Library for this (jquery.com)
Just add this to your header:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js">
<script type="text/javascript">
$(document).ready(function() {
$('li').hover(function(){
$('#homepage_container').css('background-image' : 'whatever.png');
}
});
</script>
If you don't care about IE6, you could do it with CSS:
#homepage_container { background: url(normal.png); }
#homepage_container:hover { background: url(hover.png); }

JavaScript highlight table cell on tab in field

I have a website laid out in tables. (a long mortgage form)
in each table cell is one HTML object. (text box, radio buttons, etc)
What can I do so when each table cell is "tabbed" into it highlights the cell with a very light red (not to be obtrusive, but tell the user where they are)?
Use jQuery to make your life easier, and you can do something like this:
$('#mytableid input').focus( function() {
$(this).addClass('highlight');
}).blur( function() {
$(this).removeClass('highlight');
});
This is basically saying when any input element in your table is under focus add the "highlight" class to it, and once it loses focus remove the class.
Setup your css as:
input.highlight { background-color: red; }
and you should be set.
This is the table I tested my code on:
<table id="myTable">
<tr>
<td><input type="text" value="hello" /></td>
<td><input type="checkbox" name="foo" value="2" /></td>
<td><input type="button" value="hi" /></td>
</tr>
</table>
Here is the code that worked:
// here is a cross-browser compatible way of connecting
// handlers to events, in case you don't have one
function attachEventHandler(element, eventToHandle, eventHandler) {
if(element.attachEvent) {
element.attachEvent(eventToHandle, eventHandler);
} else if(element.addEventListener) {
element.addEventListener(eventToHandle.replace("on", ""), eventHandler, false);
} else {
element[eventToHandle] = eventHandler;
}
}
attachEventHandler(window, "onload", function() {
var myTable = document.getElementById("myTable");
var myTableCells = myTable.getElementsByTagName("td");
for(var cellIndex = 0; cellIndex < myTableCells.length; cellIndex++) {
var currentTableCell = myTableCells[cellIndex];
var originalBackgroundColor = currentTableCell.style.backgroundColor;
for(var childIndex = 0; childIndex < currentTableCell.childNodes.length; childIndex++) {
var currentChildNode = currentTableCell.childNodes[childIndex];
attachEventHandler(currentChildNode, "onfocus", function(e) {
(e.srcElement || e.target).parentNode.style.backgroundColor = "red";
});
attachEventHandler(currentChildNode, "onblur", function(e) {
(e.srcElement || e.target).parentNode.style.backgroundColor = originalBackgroundColor;
});
}
}
});
There are probably things here you could clean up, but I whipped this together quickly. This works even if there are multiple things in each cell.
This would be much easier, it should go without saying, if you used a library to assist you in this work - jQuery and MochiKit are the two I favor, though there are others that would work just as well.
Between the time I started writing this answer and the time I posted it, someone posted code that shows how you would do something like this in jQuery - as you can see, much shorter! Although I love libraries, I know some people either can't or will not use a library - in those cases my code should do the job.
Possibly:
<script type="text/javascript">
//getParent(startElement,"tagName");
function getParent(elm,tN){
var parElm = elm.parentNode;
while(parElm.tagName.toLowerCase() != tN.toLowerCase())
parElm = parElm.parentNode;
return parElm;
}
</script>
<tr><td><input type="..." onfocus="getParent(this,'td').style.backgroundColor='#400';" onblur="getParent(this,'td').style.backgroundColor='';"></td></tr>

Categories

Resources