[组件] TopN 排行榜
废话不说,直接看代码,最后会给出一个示例:
/**
* TopN 排行榜组件
*
* @param {Array} data 排行数据
* @param {Number} N 即TopN的N
* @param {Object} config 配置对象,格式为:
* {
* headers: [], // 每一项的header信息,如"北京"的header为"城市",
* // 每一项都是HTML字符串
* // 也可以是Function,返回一段HTML代码
* showHeader: false, // 是否显示headers
*
* keys: [], // 每一项数据的key
* values: [], // 如需定义结构,元素为Function,返回一段HTML
* // 一般传null即可
* mainKey: 'xx', // 比较项
* sorted: false, // 数据是否已排序
* }
*
* headers(如果有), keys, values的长度保持一致
*
* 如有色块,约定className为valueBar,如果色块旁边需附有值说明,约定className
* 为valueLiteral,如下:
* <div class="valueBar"></div><div class="valueLiteral">100</div>
*/
function TopN(data, N, config) {
this.data = data;
this.N = N;
this.config = config || {};
// 对应的DOM节点
this.node = null;
if (!this.config.sorded) {
this.data.sort(this.sort());
}
}
TopN.prototype = {
constructor: TopN,
/**
* @param {HTMLElement} parentNode 插入TopN组件的父元素
*/
initDOM: function() {
return function(parentNode) {
if (!parentNode || parentNode.nodeType !== 1) return;
var config = this.config, html = ['<table class="ui_TopN">'],
i, len = config.keys.length;
// 加col
html.push('<colgroup>');
for (i = 1; i <= len; i++) {
html.push('<col class="column' + i + '" />');
}
html.push('</colgroup>');
// 拼装header部分
if (config.showHeader) {
html.push('<thead><tr>');
var headers = config.headers;
for (i = 0, len = headers.length; i < len; i++) {
html.push('<th>');
html.push(headers[i] || ' ');
html.push('</th>');
}
html.push('</tr></thead>');
}
// 拼装排行部分
html.push('<tbody>');
// 遍历前N 项数据
var keys = config.keys, key,
values = config.values, value,
items = this.data, item,
j, size = values.length;
for (i = 0, len = this.N; i < len; i++) {
item = items[i];
html.push('<tr>');
// 遍历每项数据的keys
for (j = 0; j < size; j++) {
key = keys[j];
value = values[j];
if (key) {
key = item[key];
} else {
// key为空表示序号项
key = i + 1;
}
if (typeof value === 'function') {
value = value(key);
} else {
value = key;
}
html.push('<td>');
html.push(value);
html.push('</td>');
}
html.push('</tr>');
}
html.push('</tbody></table>');
var doc = parentNode.ownerDocument,
div = doc.createElement('div');
div.innerHTML = html.join('');
this.node = div.firstChild;
parentNode.appendChild(this.node);
if ($('valueBar', this.node)[0]) {
this.autoWidth();
}
}
}(),
autoWidth: function() {
var maxValue = this.data[0][this.config.mainKey], maxWidth;
var valueBars = $('valueBar', this.node), bar,
valueLiterals = $('valueLiteral', this.node), literal;
// 进到这里,valueBars肯定不为空,所以就看valueLiterals是否为空
maxWidth = valueBars[0].parentNode.offsetWidth - (valueLiterals[0] ? valueLiterals[0].offsetWidth : 0);
var data = this.data, mainKey = this.config.mainKey, percentage, width;
for (var i = 0, len = valueBars.length; i < len; i++) {
bar = valueBars[i];
percentage = data[i][mainKey] / maxValue;
width = maxWidth * percentage;
width = Math.max(4, width);
bar.style.width = width + 'px';
if (!bar.innerHTML) {
bar.innerHTML = ' ';
}
}
},
/**
* 排序方法,作为Array.prototype.sort()的参数
* @return {Function}
*/
sort: function() {
var key = this.config.mainKey;
return function(item1, item2) {
if (item1 && typeof item1[key] !== 'undefined' &&
item2 && typeof item2[key] !== 'undefined') {
var value1 = '' + item1[key];
var value2 = '' + item2[key];
return -1 * value1.localeCompare(value2);
}
}
}
}
function $(className, node){
node = node || document;
return node.getElementsByClassName(className);
}
接着给例子,请先把TopN组件存为topN.js:
<!DOCTTYPE html>
<html>
<head>
<script src="topN.js"></script>
<script>
var data = [
{name:'北京', input:5000},
{name:'上海', input:4000},
{name:'深圳', input:6000},
{name:'广州', input:3000},
{name:'天津', input:7000},
]
var top3 = new TopN(data, 3, {
headers: [null, '城市', '值', '还是城市'],
showHeader: true,
keys: [null, 'name', 'input', 'name'],
values: [null, null, function(s){
return '<div class="valueBar"></div><span class="valueLiteral">'+s+'</span>';
}, function(value){
return '<b>'+value+'</b>'
}],
mainKey: 'input'
})
window.onload = function(){
top3.initDOM(document.body);
}
</script>
<style>
ol {
border:2px solid blue;
}
.column3 {
width:300px;
}
.valueBar {
background:blue;
}
</style>
</head>
<body>
</body>
</html>

浙公网安备 33010602011771号