原生javaScript手写简单的table.js

JS

! function(global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
        (global.Table = factory());
}(this, function() {
    return function(e) {
        //首先传递的参数必须是对象   否则报错
        function isObject(obj) {
            return typeof obj === 'object' && obj != null;
        }

        function isArray(arr) {
            return arr.constructor === 'Array';
        }

        function create(ele) {
            return _doc.createElement(ele);
        }
        var _doc = document;
        if(!isObject(e) || isArray(e)) {
            throw new Error("数据类型错误");
        }
        
        var _pros ={
                        el : e.el,
                        url : e.url || '',
                        data : e.data || [],
                        sort : typeof e.sort === 'boolean' && e.sort || false,
                        columns : e.columns || [],
                        queryParams : {},
                        rowNumber:typeof e.rowNumber === 'boolean' && e.rowNumber || false,
                        firstCheckBox:typeof e.firstCheckBox === 'boolean' && e.firstCheckBox || false,
                        slectRow:e.slectRow,
                        getSelects:e.getSelects ||''
                    }
        ///ajax(_pros.url, _pros.queryParams, init());
        var table,tableParentNode,thead,tbody,tfoot,rows;
        ~function init() {
            //获取表格的父级元素
            tableParentNode = _doc.querySelector(_pros.el);
            table = create("table");
            table.className = "Table";
            table.id = 'table' + _pros.el;
            tableParentNode.appendChild(table);
            thead = create("thead");
            table.appendChild(thead);
            tbody = create("tbody");
            table.appendChild(tbody);
            tfoot = create("tfoot");    
            table.appendChild(tfoot);
            //添加表头
            var str = "";
            if(_pros.rowNumber) str += "<th style='display:block;30px;color:#ccc0;background-color: #cccccc29;'></th>";
            if(_pros.firstCheckBox)str +="<th style='30px;color:#ccc0;background-color: #cccccc29;130px;'></th>";
            _pros.columns.forEach(function(content) {
                str += "<th>" + content.field + "</th>";
            });
            thead.innerHTML = str;
            innsertTbody();
            innsertTfoot();
        }();

        function innsertTbody() {
            //添加表体
            rows = [];
            _pros.data.forEach(function(content,i) {
                var tr = create("tr");
                var str = "";
                if(_pros.rowNumber)str += "<td style='background-color:rgba(81, 238, 62, 0.64);color:#FFF;display: block;30px'>" +(i+1)+ "</td>";
                if(_pros.firstCheckBox) str += "<td style='background-color:rgba(167, 143, 30, 0.21);color:#FFF;100px;'><input type='checkbox' style='16px;'></input></td>";
                _pros.columns.forEach(function(e) {
                    if(content[e.data]){
                        str += "<td>" + content[e.data] + "</td>";
                    }
                });
                rows.push(content);
                tr.onclick =_callFn;
                tr.innerHTML = str;
                tbody.appendChild(tr);
            })
        }
        
        
        function _callFn(){
            //console.log(this);
            var input = this.querySelector('input');
            if(input)input.checked =!input.checked;
            _pros.slectRow.call(this,rows,this.rowIndex-1);
        }
        
        function _callGetSelects(){
            var inputs = _doc.querySelector('input');
            inputs.forEach(function(){
                if(input.checked){
                    
                }
            })
            _pros.getSelects.call(this,rows,this.rowIndex-1);
        }
        
        function innsertTfoot() {
            //添加表尾
            var tr = create("tr");
            var footstr = "<td style='100%'><div>尾页</div><div>1</div> <div>首页</div><button id='exportExcle'>导出EXCLE</button> </td>";
            tr.innerHTML = footstr;
            tfoot.appendChild(tr);
        }

        _doc.querySelector('#exportExcle').onclick = exportExcle;
        //导出EXCLE
        function exportExcle() {
            if(getExplorer() == 'ie') {
                var curTbl = _doc.getElementById("table");
                var oXL = new ActiveXObject("Excel.Application");

                //创建AX对象excel
                var oWB = oXL.Workbooks.Add();
                //获取workbook对象
                var xlsheet = oWB.Worksheets(1);
                //激活当前sheet
                var sel = _doc.body.createTextRange();
                sel.moveToElementText(curTbl);
                //把表格中的内容移到TextRange中
                sel.select;
                //全选TextRange中内容
                sel.execCommand("Copy");
                //复制TextRange中内容
                xlsheet.Paste();
                //粘贴到活动的EXCEL中
                oXL.Visible = true;
                //设置excel可见属性

                try {
                    var fname = oXL.Application.GetSaveAsFilename("Excel.xls", "Excel Spreadsheets (*.xls), *.xls");
                } catch(e) {
                    print("Nested catch caught " + e);
                } finally {
                    oWB.SaveAs(fname);

                    oWB.Close(savechanges = false);
                    //xls.visible = false;
                    oXL.Quit();
                    oXL = null;
                    //结束excel进程,退出完成
                    //window.setInterval("Cleanup();",1);
                    idTmr = window.setInterval("Cleanup();", 1);
                }
            } else {
                tableToExcel(table, "报表管理信息")
            }
        }

        var idTmr;

        function getExplorer() {
            var explorer = window.navigator.userAgent;
            //ie
            if(explorer.indexOf("MSIE") >= 0) {
                return 'ie';
            }
            //firefox
            else if(explorer.indexOf("Firefox") >= 0) {
                return 'Firefox';
            }
            //Chrome
            else if(explorer.indexOf("Chrome") >= 0) {
                return 'Chrome';
            }
            //Opera
            else if(explorer.indexOf("Opera") >= 0) {
                return 'Opera';
            }
            //Safari
            else if(explorer.indexOf("Safari") >= 0) {
                return 'Safari';
            }
        }

        function Cleanup() {
            window.clearInterval(idTmr);
            CollectGarbage(table);
        }

        /*
            template : 定义文档的类型,相当于html页面中顶部的<!DOCTYPE> 声明。(个人理解,不确定)
            encodeURIComponent:解码
            unescape() 函数:对通过 escape() 编码的字符串进行解码。
            window.btoa(window.encodeURIComponent(str)):支持汉字进行解码。
            w :匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’
            replace()方法:用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
            {(w+)}:匹配所有 {1个或更多字符} 形式的字符串;此处匹配输出内容是 “worksheet”
                    正则中的() :是为了提取匹配的字符串。表达式中有几个()就有几个相应的匹配字符串。
                    讲解(/{(w+)}/g, function(m, p) { return c[p]; } :
                /{(w+)}/g 匹配出所有形式为“{worksheet}”的字符串;
                function参数:  m  正则所匹配到的内容,即“worksheet”;
                                p  正则表达式中分组的内容,即“(w+)”分组中匹配到的内容,为“worksheet”;
                c :为object,见下图3
                c[p] : 为“worksheet”

        */
        var tableToExcel = (function() {
            var uri = 'data:application/vnd.ms-excel;base64,',
                template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>',
                base64 = function(s) {
                    return window.btoa(unescape(encodeURIComponent(s)))
                },
                // 下面这段函数作用是:将template中的变量替换为页面内容ctx获取到的值
                format = function(s, c) {
                    return s.replace(/{(w+)}/g,
                        function(m, p) {
                            return c[p];
                        }
                    )
                };
            return function(table, name, filename) {
                if(!table.nodeType) table = _doc.getElementById(table.id)
                // 获取表单的名字和表单查询的内容
                var ctx = {
                    worksheet: name || 'Worksheet',
                    table: table.innerHTML
                };
                // format()函数:通过格式操作使任意类型的数据转换成一个字符串
                // base64():进行编码
                window.location.href = uri + base64(format(template, ctx))
            }
        })()

        //获取《style》标签样式
        function getStyle(obj, attr) {
            return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr];
        }

        //添加样式
        !function addStyle() {
            var styleNode = create("style");
            var tableMargin = parseFloat(getStyle(table, "margin-right"));
            var width = table.offsetWidth - tableMargin * 2;
            styleNode.innerHTML = "table tr,th,td{" + width + "px}";
            var no_height_style="thead{padding-right: 0em;}thead tr:first-child,th{box-shadow: -1px -1.1px #CCC, 1.2px -1px #CCC;border:1px solid #ccc}";
            //自定义高度
            if(e.height) {
                //指定了高度
                var o = tableParentNode.offsetHeight = e.height;
                var _height = e.height + thead.offsetHeight;
                if(_height >= o){
                    tbody.style.height = (o - thead.offsetHeight) + "px";
                    styleNode.innerHTML += no_height_style;
                    //内容高度可以完全展示时
                    if(tbody.scrollHeight == tbody.clientHeight || tbody.scrollHeight < tbody.clientHeight) {
                        //alert();
                        styleNode.innerHTML +="tbody tr:last-child,tbody tr:last-child td{border:1px solid #ccc;border-bottom:2px solid #ccc}";
                        //styleNode.innerHTML += no_height_style;
                    }
                } 
            } else {
                //如果没有指定tbody高度
                styleNode.innerHTML += no_height_style;
            }
            _doc.head.appendChild(styleNode);
        }()

        _pros.sort && makeSorttable(table);
        //排序
        var flag = true;
        //选择tr的第几个<td>的指进行排序
        function sortRows(table, n) {
            //var tbody = table.getElementsByTagName("tbody")[0];
            var tbody = table.tBodies[0];
            var rows = tbody.getElementsByTagName('tr');
            rows = Array.prototype.slice.call(rows, 0);
            rows.sort(function(row1, row2) {
                var cell1 = row1.getElementsByTagName("td")[n];
                var cell2 = row2.getElementsByTagName("td")[n];
                if(cell1 && cell2) {
                    var val1 = cell1.textContent || cell1.innerText;
                    var val2 = cell2.textContent || cell2.innerText;
                    if(val1 > val2) return flag ? 1 : -1;
                    else if(val1 < val2) return flag ? -1 : 1;
                    else return 0;
                }
            })
            for(var i = 0, len = rows.length; i < len; i++) {
                tbody.appendChild(rows[i]);
            }
        };
        //选择表格th进行排序
        function makeSorttable(table) {
            var headers = table.getElementsByTagName("th");
            /*for (var i=0,len = headers.length;i<len;i++) {
                (function(n){//使用闭包
                    headers[i].onclick=function(){
                        sortRows(table,n);
                        flag = !flag;
                    }
                })(i)
            }*/
            //改进 
            for(let i = 0, len = headers.length; i < len; i++) {
                headers[i].onclick = function() {
                    sortRows(table, i);
                    flag = !flag;
                }
            }
        }

        // ajax封装
        function ajax(url, data, callback, cache, async, type, dataType, traditional, error) {
            // layer.load();
            var type = type || 'post'; //请求类型
            var dataType = dataType || 'json'; //接收数据类型
            var async = async || false; //异步请求
            // var alone = alone || false;//独立提交(一次有效的提交)
            var cache = cache || false; //浏览器历史缓存
            var traditional = traditional || false; //如果你想要用传统的方式来序列化数据,那么就设置为true
            var success = function(data) {
                //  console.log(data);
                //layer.closeAll();
                if(data.error == 0) { //服务器处理成功
                    if(callback != null) {
                        callback(data.data);
                    }
                } else { //服务器处理失败
                    toastr.error(data.info);
                }
            };
            var error = error || function(data) {
                console.log(data);
                layer.closeAll();
                if(data.status == 404) {
                    toastr.error('请求失败,请求未找到');
                } else if(data.status == 503) {
                    toastr.error('请求失败,服务器内部错误');
                } else {
                    toastr.error(data.responseText);
                }
            };
            $.ajax({
                'url': url,
                'data': data,
                'type': type,
                'dataType': dataType,
                'async': async,
                'success': success,
                'cache': cache,
                'error': error,
                'traditional': traditional,
                'jsonpCallback': 'jsonp' + (new Date()).valueOf().toString().substr(-4),
            });
        }

        // submitAjax(post方式提交)同步
        function submitAjax(form, success, cache) {
            cache = cache || true;
            var url = form.attr('action');
            var data = form.serialize();
            ajax(url, data, success, cache, false, 'post', 'json');
        }

        // ajax提交(post方式提交)traditional 值为true 用传统的方式来序列化数据,同步
        function post(url, data, success, cache) {
            ajax(url, data, success, cache, false, 'post', 'json', true);
        }
    }
})
View Code

CSS

*{margin:0;padding:0}
html,body{height: 100%;width: 100%;}
table,tr,th,td{border-collapse:collapse ;}
tr,th,td{
    padding: 0;
    margin: 0;
    border: 1px solid #ccc;
    border-bottom: 0;
}
tr:not(:first-child),td:not(:last-child),tr:not(:last-child){
    box-shadow: -1px -1.1px #CCC, 1.2px -1px #CCC;
}
tr:first-child,th:last-child,tr:last-child{
    border-right:0;
}
table,thead,tbody{display:block;}
table{
    width: 80%;
    text-align: center;
    margin: 0 auto;
    table-layout: fixed;
    position: relative;
    word-wrap: break-word;
    word-break: break-all;
}
thead{
    padding-right: 0.8em;
    border: 1px solid #ccc;
}

tbody{
    
    overflow:auto;
    border: 1px solid #ccc;
}

tr:hover:not(:last-child){
    background-color:#F0AD4E;
}
tfoot tr, tfoot tr td{
    border: 0;
    display: block;
}
tfoot td div{
    color: #2a6496;
    width: 40px;
    float: right;
    margin-left: 2px;
    margin-top: 2px;
}
    
tfoot td div:first-child,tfoot td div:last-child{
    color: #FFF;
    border:0;
    background-color: #337ab7;
}
::-webkit-scrollbar 
{ 
    width: 6px; 
    height: 16px; 
    background-color: #F5F5F5; 
} 
   
/*定义滚动条轨道 内阴影+圆角*/ 
::-webkit-scrollbar-track 
{ 
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); 
    border-radius: 10px; 
    background-color: #b6d0c5; 
} 
   
/*定义滑块 内阴影+圆角*/ 
::-webkit-scrollbar-thumb 
{ 
    border-radius: 10px; 
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); 
    background-color: #b9c355; 
}
View Code

DEMO

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript" src="js/table.js" ></script>
        <link rel="stylesheet" href="css/table.css" />
    </head>
    <body>
        <div id="tb"></div>
    </body>
    <script>
        var t = new Table({
            el:'#tb',
            columns:[
                {data:'sex',field:'性别'},
                {data:'name',field:'姓名'},
                {data:'address',field:'地址'},
                {data:'age',field:'年龄'},
            ],
            rowNumber:true,
            height:400,
            //firstCheckBox:true,
            data:[
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'},
                {name:'王五',age:'11',sex:'',address:'三国'},
                {name:'赵六',age:'51',sex:'',address:'水浒'},
                {name:'孙倩',age:'51',sex:'',address:'虹口'},
                {name:'张三',age:'28',sex:'',address:'廊坊大城'},
                {name:'李四',age:'41',sex:'',address:'西游'}
            ],
            sort:true,
            slectRow:function(e,i){
                console.log("下表 ======== "+i);
                console.log(e[i].name+"-----"+e[i].address);
            }
        });
    </script>
</html>
View Code
原文地址:https://www.cnblogs.com/wang-yi/p/9867131.html