Skip to content

Instantly share code, notes, and snippets.

@andyford
Created May 1, 2013 19:48
Show Gist options
  • Select an option

  • Save andyford/5497825 to your computer and use it in GitHub Desktop.

Select an option

Save andyford/5497825 to your computer and use it in GitHub Desktop.
EmChart
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="EmChart is a lookup table for converting pixel values to EM values and calculating line-height" />
<meta name="author" content="Andy Ford, Ford Interactive" />
<title>EmChart</title>
<!--
EmChart was developed by Andy Ford of Ford Interactive.
Feel free to copy and re-use this code
Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
Please credit Ford Interactive in any derivative work - thanks
You are free:
* to copy, distribute, display, and perform the work
* to make derivative works
* to make commercial use of the work
Under the following conditions:
by Attribution.
--------------
You must attribute the work in the manner specified by the author or licensor.
sa
--
Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.
* For any reuse or distribution, you must make clear to others the license terms of this work.
* Any of these conditions can be waived if you get permission from the copyright holder.
EmChart is enhanced by (but can be used without) the 'Unobtrusive Table Actions Script' by Brian McAllister of frequency-decoder.com
http://www.frequency-decoder.com/2007/11/15/unobtrusive-table-actions-script
All EmChart code (HTML, CSS & JavaSscript) is contained within this sinlge page to keep the page portable.
For example, you could take it with you on a thumb drive or run it as a standalone app using Fluid http://fluidapp.com/
-->
<style type="text/css">
html, body, div, span,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, cite, code,
del, dfn, em, font, img, ins,
strike, strong, sub, sup,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
}
body {
font-size: 62.5%;
line-height: 1;
font-family: sans-serif;
color: #333;
background: #fff;
}
:focus { outline: 0; }
p, ul, ol, dl, table, blockquote {
margin: 0 0 1em;
line-height: 1.5em;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
th, td {
padding: .5em;
border: 1px solid #bbb;
font-size: 1em;
line-height: 1.2;
text-align: left;
vertical-align: middle;
}
tr td.header {
font-weight: bold;
background: #d9d9d9 !important;
}
tr td.one { background: #ebebeb; }
/*td.half, td.two { background: #ccc; }
td.quart, td.four { background: #e9e9e9; }*/
tr td.colhov { background: #dfdfdf !important; /*color: #fff;*/ }
tr:hover td { background: #ccc !important; /*color: #fff !important;*/ }
tr.alt td { background: #f5f5f5; }
tfoot { font-style: italic; }
table tr td:hover { background: #444 !important; color: #fff !important; cursor: pointer; }
tr.rowsel td { background: #666 !important; color: #fff !important; }
table tr td.header.colhov,
table tr:hover td.header { background: #666 !important; color: #fff !important; }
</style>
<script type="text/javascript">
/*
Table actions plug-in v0.8 by frequency-decoder.com
Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
Please credit frequency decoder in any derivative work - thanks
You are free:
* to copy, distribute, display, and perform the work
* to make derivative works
* to make commercial use of the work
Under the following conditions:
by Attribution.
--------------
You must attribute the work in the manner specified by the author or licensor.
sa
--
Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.
* For any reuse or distribution, you must make clear to others the license terms of this work.
* Any of these conditions can be waived if you get permission from the copyright holder.
NOTE: Parts of this script is based on a script originally developped by the veritable Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html)
*/
var fdTableActions = {
tableCache:{},
init:function() {
var tables = document.getElementsByTagName("table");
var rowAlt, colHover, rowHover, rowSelect, rowSelectCallback, cellHover, rowList, rowArr, colObj, elem, rowLength, workArr, celCount, rowSpan, colSpan, cel, colHead, rowL, colL;
var uniqueID = 0;
var colspan = "colspan";
var rowspan = "rowspan";
/*@cc_on
/*@if(@_win32)
colspan = "colSpan";
rowspan = "rowSpan";
/*@end
@*/
for(var k = 0, table; table = tables[k]; k++) {
// Grab the className for the alternate rows
rowAlt = table.className.search(/rowstylealt-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylealt-([\S]+)/)[1];
// Highlight columns?
colHover = table.className.search(/colstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/colstylehover-([\S]+)/)[1];
// Grab the className for the rowStyleHover
rowHover = table.className.search(/rowstylehover-([\S-]+)/) == -1 ? "" : table.className.match(/rowstylehover-([\S]+)/)[1];
// Do we select the rows
rowSelect = table.className.search(/rowselect-([\S-]+)/) == -1 ? "" : table.className.match(/rowselect-([\S]+)/)[1];
// Single or multiple row selection possible
rowSelectSingle = table.className.search(/rowselectsingle/) != -1;
// Do we have a callback for this table whenever a row is selected?
rowSelectCallback = table.className.search(/rowselectcallback-([\S-]+)/) == -1 ? "" : table.className.match(/rowselectcallback-([\S]+)/)[1];
// Replace "-" with "." to enable Object.method callbacks
rowSelectCallback = rowSelectCallback.replace("-", ".");
// Current TH or TD
cellHover = table.className.search(/cellhover-([\S-]+)/) == -1 ? "" : table.className.match(/cellhover-([\S]+)/)[1];
// Do we even need to continue?
if(!(rowAlt || rowHover || colHover || rowSelect || cellHover)) continue;
// Create a table ID if necessary
if(!table.id) table.id = "fdTable-" + uniqueID++;
// Cache this tables details
fdTableActions.tableCache[table.id] = { "trCache":[], "rowSelectSingle":rowSelectSingle, "rowSelect":rowSelect, "rowSelectCallback":rowSelectCallback, "lastColCache":[0,0], "rowHover":rowHover, "colHover":colHover };
/*@cc_on
@if (@_jscript_version >= 5.7)
if(document.compatMode == "BackCompat") fdTableActions.tableCache[table.id].req = true;
@else
fdTableActions.tableCache[table.id].req = true;
@end
@*/
/*@cc_on
/*@if(@_win32)
if(fdTableActions.tableCache[table.id].req) {
fdTableActions.tableCache[table.id].lastRow = null;
fdTableActions.tableCache[table.id].lastCell = null;
fdTableActions.tableCache[table.id].cellHover = cellHover;
};
/*@end
@*/
rowArr = [];
rowList = table.getElementsByTagName('tr');
for(var i = 0;i < rowList.length;i++){
colObj = [];
elem = rowList[i].firstChild;
do {
if(elem.tagName && elem.tagName.toLowerCase().search(/td|th/) != -1) {
colObj[colObj.length] = elem;
};
elem = elem.nextSibling;
} while(elem);
if(i % 2 == 0 && rowAlt) rowList[i].className = rowList[i].className + " " + rowAlt;
rowArr[rowArr.length] = colObj;
};
/*@cc_on
/*@if (@_win32)
if(fdTableActions.tableCache[table.id].req) {
if(!cellHover && !rowSelect && !colHover && !rowHover) continue;
} else {
if(!colHover && !rowSelect) continue;
};
@else @*/
if(!colHover && !rowSelect) continue;
/*@end
@*/
if(rowArr.length > 0){
/* Attribution: Parts of the following code based on an original script by Richard Cornford (http://www.litotes.demon.co.uk/example_scripts/tableHighlighter.html) */
if(colHover) {
rowLength = rowArr[0].length;
for(var c = 0;c < rowArr[0].length;c++){
if(rowArr[0][c].getAttribute(colspan) > 1){
rowLength = rowLength + (rowArr[0][c].getAttribute(colspan) - 1);
};
};
workArr = new Array(rowArr.length);
for(var c = rowArr.length;c--;){
workArr[c] = new Array(rowLength);
};
colHead = new Array(rowLength);
for(var c = rowLength;c--;){
colHead[c] = [];
};
for(var c = 0;c < workArr.length;c++) {
celCount = 0;
for(var i = 0;i < rowLength;i++) {
if(!workArr[c][i]) {
cel = rowArr[c][celCount];
colSpan = (cel.getAttribute(colspan) && cel.getAttribute(colspan) > 1) ? cel.getAttribute(colspan) : 1;
rowSpan = (cel.getAttribute(rowspan) && cel.getAttribute(rowspan) > 1) ? cel.getAttribute(rowspan) : 1;
cel.className = cel.className + " fdCellProcessed-" + i + "-" + (i + Number(colSpan));
for(var t = 0;((t < colSpan)&&((i+t) < rowLength));t++){
for(var n = 0;((n < rowSpan)&&((c+n) < workArr.length));n++){
workArr[(c+n)][(i+t)] = cel;
};
colHead[(i+t)][colHead[(i+t)].length] = cel;
};
if(++celCount == rowArr[c].length) break;
};
};
};
/* End attribution */
fdTableActions.tableCache[table.id].colCache = colHead;
};
/*@cc_on
/*@if (@_win32)
fdTableActions.addEvent(table, "mouseleave", fdTableActions.tableEvent);
@else @*/
fdTableActions.addEvent(table, "mouseout", fdTableActions.tableEvent);
/*@end
@*/
fdTableActions.addEvent(table, "mouseover", fdTableActions.tableEvent);
if(rowSelect) {
fdTableActions.addEvent(table, "click", fdTableActions.clickEvent);
};
};
};
},
clickEvent:function(e) {
e = e || window.event;
var tr, cell;
if(e.target) tr = e.target;
else if (e.srcElement) tr = e.srcElement;
while(true) {
if(tr && !cell && tr.nodeName && tr.nodeName.search(/^(TD|TH)$/) != -1) { cell = tr; }
else if(tr && tr.nodeName && tr.nodeName.search(/^(TR)$/) != -1) { break; };
try { tr = tr.parentNode; } catch(err) { break; };
};
if(!tr || !tr.nodeName || tr.nodeName.search(/^(TR)$/) == -1) { return; };
var remove = (tr.className.search(fdTableActions.tableCache[this.id].rowSelect) != -1);
var action = true;
if(fdTableActions.tableCache[this.id].rowSelectCallback) {
var func;
if(fdTableActions.tableCache[this.id].rowSelectCallback.search(".") != -1) {
var split = fdTableActions.tableCache[this.id].rowSelectCallback.split(".");
func = window;
for(var i = 0, f; f = split[i]; i++) {
if(f in func) {
func = func[f];
} else { break; };
};
} else if(fdTableActions.tableCache[this.id].rowSelectCallback in window) {
func = window[fdTableActions.tableCache[this.id].rowSelectCallback];
} else if("rowSelectCallback" in window) {
func = window["rowSelectCallback"];
};
if(typeof func == "function") {
action = func({"table":this, "cell":cell, "row":tr, "remove":remove, "rows":fdTableActions.tableCache[this.id].trCache.concat([])});
};
func = null;
};
if(action) {
if(remove) {
tr.className = tr.className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
var rowArr = [];
for(var i = 0, elem; elem = fdTableActions.tableCache[this.id].trCache[i]; i++) {
if(elem != tr) rowArr[rowArr.length] = elem;
};
fdTableActions.tableCache[this.id].trCache = rowArr;
} else {
tr.className = tr.className + " " + fdTableActions.tableCache[this.id].rowSelect;
if(fdTableActions.tableCache[this.id].rowSelectSingle && fdTableActions.tableCache[this.id].trCache.length) {
fdTableActions.tableCache[this.id].trCache[0].className = fdTableActions.tableCache[this.id].trCache[0].className.replace(fdTableActions.tableCache[this.id].rowSelect, "");
fdTableActions.tableCache[this.id].trCache = [];
};
fdTableActions.tableCache[this.id].trCache[fdTableActions.tableCache[this.id].trCache.length] = tr;
};
};
},
tableEvent:function(e) {
e = e || window.event;
var p;
if(e.type == "mouseout") {
p = e.toElement || e.relatedTarget;
} else {
p = e.target || e.srcElement;
if (p.nodeType && p.nodeType == 3) p = p.parentNode;
};
while(true) {
if(p && p.nodeName && p.nodeName.search(/^(TD|TH)$/) != -1) { break; };
try { p = p.parentNode; } catch(err) { break; };
};
// Get the old column range
var colRangeOld = fdTableActions.tableCache[this.id].lastColCache;
var r = [];
var n = [];
if(e.type == "mouseover" && p && p.nodeName.search(/^(TD|TH)$/) != -1) {
// Do current cell & row for bloody IE
/*@cc_on
/*@if(@_win32)
if(fdTableActions.tableCache[this.id].req) {
if(fdTableActions.tableCache[this.id].rowHover) {
var tr = p.parentNode;
if(fdTableActions.tableCache[this.id].lastRow != tr) {
if(fdTableActions.tableCache[this.id].lastRow) {
fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(new RegExp(fdTableActions.tableCache[this.id].rowHover, "g"),"");
fdTableActions.tableCache[this.id].lastRow = false;
};
tr.className = tr.className+ " " + fdTableActions.tableCache[this.id].rowHover;
fdTableActions.tableCache[this.id].lastRow = tr;
};
};
if(fdTableActions.tableCache[this.id].cellHover) {
if(fdTableActions.tableCache[this.id].lastCell != p) {
if(fdTableActions.tableCache[this.id].lastCell) {
fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(new RegExp(fdTableActions.tableCache[this.id].cellHover, "g"),"");
fdTableActions.tableCache[this.id].lastCell = false;
};
p.className = p.className + " " + fdTableActions.tableCache[this.id].cellHover;
fdTableActions.tableCache[this.id].lastCell = p;
};
};
};
/*@end
@*/
if(!fdTableActions.tableCache[this.id].colHover || p.className.search("fdCellProcessed-") == -1) return;
var m = p.className.match(/fdCellProcessed-([\d]+)-([\d]+)/);
m[1] = Number(m[1]);
m[2] = Number(m[2]);
if(fdTableActions.tableCache[this.id].lastColCache[0] == m[1] && fdTableActions.tableCache[this.id].lastColCache[1] == m[2]) return;
for(var i = colRangeOld[0]; i < colRangeOld[1]; i++) {
if(i < m[1] || i >= m[2]) {
r[r.length] = i;
};
};
fdTableActions.tableCache[this.id].lastColCache = [m[1], m[2]];
n = [m[1], m[2]];
} else {
/*@cc_on
/*@if(@_win32)
if(fdTableActions.tableCache[this.id].req) {
if(fdTableActions.tableCache[this.id].lastRow) {
fdTableActions.tableCache[this.id].lastRow.className = fdTableActions.tableCache[this.id].lastRow.className.replace(fdTableActions.tableCache[this.id].rowHover,"");
fdTableActions.tableCache[this.id].lastRow = null;
};
if(fdTableActions.tableCache[this.id].lastCell) {
fdTableActions.tableCache[this.id].lastCell.className = fdTableActions.tableCache[this.id].lastCell.className.replace(fdTableActions.tableCache[this.id].cellHover,"");
fdTableActions.tableCache[this.id].lastCell = null;
};
};
/*@end
@*/
if(!fdTableActions.tableCache[this.id].colHover) { return; };
for(var i = colRangeOld[0]; i <= colRangeOld[1]; i++) {
r[r.length] = i;
};
fdTableActions.tableCache[this.id].lastColCache = [0,0];
};
// Remove
if(r.length) {
for(var i = 0; i < r.length; i++) {
if(r[i] >= fdTableActions.tableCache[this.id].colCache.length) continue;
elemArr = fdTableActions.tableCache[this.id].colCache[r[i]];
for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
elem.className = elem.className.replace(fdTableActions.tableCache[this.id].colHover, "");
};
};
};
// Add
if(n.length) {
for(i = n[0]; i < n[1]; i++) {
elemArr = fdTableActions.tableCache[this.id].colCache[i];
for(var ec = 0, elem; elem = elemArr[ec]; ec++) {
if(elem.className.search(fdTableActions.tableCache[this.id].colHover) == -1) {
elem.className = elem.className + " " + fdTableActions.tableCache[this.id].colHover;
};
};
};
};
},
deselectAllRows:function(tableId) {
if(!(tableId in fdTableActions.tableCache) || !fdTableActions.tableCache[tableId].rowSelect) return;
var trList = fdTableActions.tableCache[tableId].trCache;
for(var i = trList.length; i--;) {
trList[i].className = trList[i].className.replace(fdTableActions.tableCache[tableId].rowSelect, "");
};
fdTableActions.tableCache[tableId].trCache = [];
trList = null;
},
unLoad:function() {
var table;
for(tbl in fdTableActions.tableCache) {
table = document.getElementById(tbl);
if(table) {
fdTableActions.removeEvent(table, "mouseover", fdTableActions.tableEvent);
fdTableActions.removeEvent(table, "mouseout", fdTableActions.tableEvent);
if(fdTableActions.tableCache[tbl].rowSelect) {
fdTableActions.removeEvent(table, "click", fdTableActions.clickEvent);
};
};
/*@cc_on
/*@if(@_win32)
fdTableActions.tableCache[tbl].req = fdTableActions.tableCache[tbl].lastRow = fdTableActions.tableCache[tbl].lastCell = null;
/*@end
@*/
fdTableActions.tableCache[tbl].colCache = fdTableActions.tableCache[tbl].trCache = null;
fdTableActions.tableCache[tbl] = null;
delete(fdTableActions.tableCache[tbl]);
};
},
addEvent:function(obj, type, fn) {
if( obj.attachEvent ) {
obj["e"+type+fn] = fn;
obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
obj.attachEvent( "on"+type, obj[type+fn] );
} else {
obj.addEventListener( type, fn, true );
};
},
removeEvent: function(obj, type, fn) {
if( obj.detachEvent ) {
try {
obj.detachEvent( "on"+type, obj[type+fn] );
obj[type+fn] = obj["e"+type+fn] = null;
} catch(err) {};
} else {
obj.removeEventListener( type, fn, true );
};
}
};
fdTableActions.addEvent(window, "load", fdTableActions.init);
fdTableActions.addEvent(window, "unload", fdTableActions.unLoad);
/*
makeChart() function by Andy Ford fordinteractive.com
if you need to expand the chart beyond the default 36 pixels, edit the $maxfont variable
*/
function makeChart() {
var $fontat = 1;
var $fontto = 1;
// if(isset($_GET['size'])) {
// $maxfont = $_GET['size'];
// } else {
// $maxfont = 36;
// }
var $maxfont = 36;
var $output = '';
for ($fontat = 1; $fontat <= $maxfont; $fontat++) {
$output += '<tr> <td title="' + $fontat/10 + 'em" class="header">' + $fontat + 'px</td> ';
for ($fontto = 1; $fontto <=$maxfont; $fontto++) {
var $multiplier = (Math.ceil(1000 * ($fontto / $fontat))) / 1000;
$output += '<td title="[' + $multiplier + 'em] '+ $fontto + '/' + $fontat + ' = ' + $fontto/$fontat + '" class="';
// if($multiplier==.5){ $output = $output + ' class="half"'; }
if($multiplier==1){ $output += 'one'; }
if($fontat == 1) $output += ' header';
$output += '">' + $multiplier;
if($fontat == 1) $output += 'px';
$output += '</td>';
}
$output += '</tr>';
}
document.write($output);
}
// function changeClass(elem, className1,className2)
//
// {
//
// elem.className = (elem.className == className1)?className2:className1;
//
// }
// onclick='changeClass(this,"class1","class2");'
</script>
</head>
<body>
<table class="rowstylealt-alt colstylehover-colhov rowselect-rowsel">
<script type="text/javascript">
makeChart();
</script>
</table>
<a href="http://fordinteractive.com">&copy; Andy Ford {Ford Interactive}</a> ~
<a href="http://twitter.com/andyford">twitter.com/andyford</a>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment