原生javaScript手寫簡單的table.js
阿新 • • 發佈:2018-12-18
! 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 : typeofe.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;width:30px;color:#ccc0;background-color: #cccccc29;'></th>"; if(_pros.firstCheckBox)str +="<th style='width:30px;color:#ccc0;background-color: #cccccc29;width: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;width:30px'>" +(i+1)+ "</td>"; if(_pros.firstCheckBox) str += "<td style='background-color:rgba(167, 143, 30, 0.21);color:#FFF;width:100px;'><input type='checkbox' style='width: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='width: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:" + 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); } } })