[组件] 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>

  

posted @ 2011-12-19 18:50  越己  阅读(360)  评论(0编辑  收藏  举报