Last active
August 29, 2015 14:13
-
-
Save BarakChamo/c63611ab880f56aff53f to your computer and use it in GitHub Desktop.
HotTable.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Space out content a bit */ | |
body { | |
padding-top: 20px; | |
padding-bottom: 20px; | |
} | |
/* Everything but the jumbotron gets side spacing for mobile first views */ | |
.header, | |
.marketing, | |
.footer { | |
padding-right: 15px; | |
padding-left: 15px; | |
} | |
/* Custom page header */ | |
.header { | |
border-bottom: 1px solid #e5e5e5; | |
} | |
/* Make the masthead heading the same height as the navigation */ | |
.header h3 { | |
padding-bottom: 19px; | |
margin-top: 0; | |
margin-bottom: 0; | |
line-height: 40px; | |
} | |
/* Custom page footer */ | |
.footer { | |
padding-top: 19px; | |
color: #777; | |
border-top: 1px solid #e5e5e5; | |
} | |
/* Customize container */ | |
@media (min-width: 768px) { | |
.container { | |
max-width: 730px; | |
} | |
} | |
.container-narrow > hr { | |
margin: 30px 0; | |
} | |
/* Main marketing message and sign up button */ | |
.jumbotron { | |
text-align: center; | |
border-bottom: 1px solid #e5e5e5; | |
} | |
.jumbotron .btn { | |
padding: 14px 24px; | |
font-size: 21px; | |
} | |
/* Supporting marketing content */ | |
.marketing { | |
margin: 40px 0; | |
} | |
.marketing p + h4 { | |
margin-top: 28px; | |
} | |
/* Responsive: Portrait tablets and up */ | |
@media screen and (min-width: 768px) { | |
/* Remove the padding we set earlier */ | |
.header, | |
.marketing, | |
.footer { | |
padding-right: 0; | |
padding-left: 0; | |
} | |
/* Space out the masthead */ | |
.header { | |
margin-bottom: 30px; | |
} | |
/* Remove the bottom border on the jumbotron for visual effect */ | |
.jumbotron { | |
border-bottom: 0; | |
} | |
} | |
table { | |
background-color: white; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* HotTable.js v0.0.1 | |
* | |
* A heat-table JS plugin by Barak Chamo, it's very nice. | |
* | |
*/ | |
(function (root, factory) { | |
root.hotTable = factory(root); | |
})(window || this, function (root) { | |
'use strict'; | |
var exports = {}, // Object for public APIs | |
settings, // Plugin settings | |
elm, // Root element | |
table, // Base element for the table | |
rendered, // Mark initial rendering passed | |
// Default settings | |
defaults = { | |
// Table data set | |
data: null, | |
// Formatter for cell values | |
formatter: function(val, rowIndex, colIndex){return val;}, | |
// Set first row as a header row | |
rowHeaders: true, | |
// Set first column as a header column | |
colHeaders: true, | |
// classes to be applied to the table's root element | |
className: '', | |
// Color for 'hot', or max, values | |
hot: '3B6427', | |
// Color for 'cold', or min, values | |
cold: 'DAE289', | |
// Callback before rendering and re-rendering | |
callbackBefore: function () {}, | |
// Callback after rendering and re-rendering | |
callbackAfter: function () {} | |
}; | |
// | |
// Helpers | |
// | |
/** | |
* forEach() pollyfill based on _.forEach of Underscore.js | |
* @param {Array|Object} Collection of items for iteration | |
* @param {Function} Callback function for each iteration | |
* @param {any} context for the iterator function (this) | |
*/ | |
function forEach(collection, callback, context) { | |
context = context || null; | |
if (Object.prototype.toString.call(collection) === '[object Object]') { | |
for (var prop in collection) { | |
if (Object.prototype.hasOwnProperty.call(collection, prop)) { | |
callback.call(context, collection[prop], prop, collection); | |
} | |
} | |
} else { | |
for (var i = 0, len = collection.length; i < len; i++) { | |
callback.call(context, collection[i], i, collection); | |
} | |
} | |
} | |
/** | |
* Merge destination with source | |
* @param {Object} destination object | |
* @param {Object} source object | |
*/ | |
function extend(destination, source) { | |
for (var property in source) { | |
if (source[property] && source[property].constructor && source[property].constructor === Object) { | |
destination[property] = destination[property] || {}; | |
extend(destination[property], source[property]); | |
} else { | |
destination[property] = source[property]; | |
} | |
} | |
return destination; | |
} | |
// | |
// Private Methods | |
// | |
/** | |
* Get the extent (min and max) of a 2d collection | |
* @param {Object} 2d collection | |
*/ | |
function getExtent( data ) { | |
if (!data || data.length && !data[0]) return (console.log('No Data Provided')); | |
var extent = [ | |
data[defaults.rowHeaders ? 1 : 0][defaults.colHeaders ? 1 : 0], | |
data[defaults.rowHeaders ? 1 : 0][defaults.colHeaders ? 1 : 0] | |
]; | |
// Compare each value with the current table extent | |
forEach(data, function(row, rowIndex){ | |
if (!rowIndex && defaults.rowHeaders) return; | |
forEach(row, function(cell, colIndex){ | |
if (!colIndex && defaults.colHeaders) return; | |
if (cell < extent[0]) { | |
extent[0] = cell; | |
} else if(cell > extent[1]){ | |
extent[1] = cell; | |
} | |
}); | |
}); | |
return extent; | |
} | |
/** | |
* Get a hue on a gradient by percentage | |
* @param {float} stop percentage | |
*/ | |
function getGradient( stop ) { | |
var from = defaults.cold, | |
to = defaults.hot, | |
r = Math.ceil(parseInt(from.substring(0,2), 16) * stop + parseInt(to.substring(0,2), 16) * (1-stop)), | |
g = Math.ceil(parseInt(from.substring(2,4), 16) * stop + parseInt(to.substring(2,4), 16) * (1-stop)), | |
b = Math.ceil(parseInt(from.substring(4,6), 16) * stop + parseInt(to.substring(4,6), 16) * (1-stop)); | |
return(getHex(r) + getHex(g) + getHex(b)); | |
} | |
/** | |
* Get a hex color definition from a RGB | |
* @param {int} red | |
* @param {int} green | |
* @param {int} blue | |
*/ | |
function getHex( colorValue ) { | |
colorValue = colorValue.toString(16); | |
return (colorValue.length == 1) ? '0' + colorValue : colorValue; | |
} | |
/** | |
* Get a hex color definition from a RGB | |
* @param {int} red | |
* @param {int} green | |
* @param {int} blue | |
*/ | |
function getPosition( min, max,val ) { | |
return (val - min) / (max - min); | |
} | |
/** | |
* Generate the heat table | |
* @param {array} the table's data extent | |
*/ | |
function getTable() { | |
var table = document.createElement('TABLE'), | |
extent = getExtent(defaults.data), | |
tsection; | |
// Set table classes | |
table.className = defaults.className; | |
// Each row | |
forEach(data, function(row, rowIndex){ | |
if(rowIndex === 0) tsection = table.appendChild(document.createElement('THEAD')); | |
if(rowIndex === 1) tsection = table.appendChild(document.createElement('TBODY')); | |
// Append a row to the table | |
var tr = tsection.appendChild(document.createElement('TR')); | |
// Each cell in row | |
forEach(row, function(cell, cellIndex){ | |
var elm, format; | |
// Check if column or row header | |
if ((!rowIndex && defaults.rowHeaders) || (!cellIndex && defaults.colHeaders)){ | |
format = true; | |
elm = tr.appendChild(document.createElement('TH')); | |
} else { | |
elm = tr.appendChild(document.createElement('TD')); | |
// Set element color | |
elm.style.backgroundColor = '#' + getGradient(getPosition(extent[0], extent[1], cell)); | |
} | |
// Set element text, check if formatting is needed | |
elm.innerText = format ? defaults.formatter(cell) : cell; | |
}); | |
}); | |
return table; | |
} | |
// | |
// Public Methods | |
// | |
/** | |
* Destroy the current initialization. | |
*/ | |
exports.destroy = function () { | |
// @todo Undo init... | |
}; | |
/** | |
* Initialize Plugin | |
* @param {Object} DOMElement or selector string | |
* @param {Object} custom options | |
*/ | |
exports.init = function ( element, options ) { | |
// Check if provided a selector or an element | |
elm = typeof element === 'string' ? document.querySelector(element) : element; | |
// Extend default options with custom ones | |
if (typeof options === 'object') extend(defaults, options); | |
// Render the table | |
exports.render(); | |
}; | |
/** | |
* set and re-set options | |
* @param {Object} key to be set | |
* @param {Object} value to be applies to key | |
* @param {Object} trigger re-render and callbacks to fire | |
*/ | |
exports.set = function ( key, value, silent ) { | |
defaults[key] = value; | |
if(!silent) exports.render(); | |
}; | |
/** | |
* get options | |
* @param {Object} key to get the value of | |
*/ | |
exports.get = function ( key ) { | |
return defaults[key]; | |
}; | |
/** | |
* render the heat table based on existing configuration | |
*/ | |
exports.render = function () { | |
var newTable = getTable(); | |
// Append or replace the new table; | |
table ? elm.replaceChild(newTable, table) : elm.appendChild(newTable); | |
// Keep an assignment to the new table | |
table = newTable; | |
}; | |
// | |
// exports | |
// | |
return exports; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Hot Table Demo</title> | |
<!-- Bootstrap core CSS --> | |
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> | |
<!-- Custom styles for this template --> | |
<link href="styles/demo.css" rel="stylesheet"> | |
</head> | |
<body> | |
<!-- Container --> | |
<div class="container"> | |
<!-- Header --> | |
<div class="header"> | |
<h3 class="text-muted">HotTable.js</h3> | |
</div> | |
<!-- Hot Table --> | |
<div class="jumbotron" id="heattable"></div> | |
<footer class="footer"> | |
<p>Barak Chamo 2015</p> | |
</footer> | |
</div> <!-- /container --> | |
<script src="scripts/hotTable.js"></script> | |
<script> | |
var data = [ | |
['#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'], | |
['May', 90, 81, 75, 99, 90, 82, 101, 95, 85 ], | |
['June', 98, 102, 82, 92, 84, 101, 78, 89, 100 ], | |
['July', 72, 81, 93, 88, 102, 70, 90, 100, 101 ], | |
['August', 80, 91, 80, 104, 90, 75, 84, 81, 90 ] | |
]; | |
hotTable.init('#heattable', { | |
data: data, | |
className: 'table table-bordered', | |
rowHeaders: true, | |
colHeaders: true, | |
formatter: function(val, rowIndex, colIndex){ | |
return val; | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment