构建项目

This commit is contained in:
julyp
2020-01-13 16:25:20 +08:00
parent 0635957013
commit 0d3449f259
16 changed files with 9482 additions and 2 deletions

View File

@@ -1,2 +1,25 @@
# smart-table ## Smart Table 组件库
smart table with static template
## 启动项目
npm run serve
## build 流程
npm run build
### 使用方法
```
new SmartUI.Table({
selector: '#smartTable1',
tableHeight: 300
})
new SmartUI.Table({
selector: '#smartTable2',
tableHeight: function () {
return 300
}
})
new SmartUI.Table({
selector: '#smartTable3'
})
```

31
config/webpack.common.js Normal file
View File

@@ -0,0 +1,31 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
inject: 'head'
})
],
module: {
rules: [{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
}, ]
},
output: {
filename: 'smartUtils.[chunkhash:8].js',
path: path.resolve(__dirname, '../dist')
},
}

9
config/webpack.dev.js Normal file
View File

@@ -0,0 +1,9 @@
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
}
});

11
config/webpack.prod.js Normal file
View File

@@ -0,0 +1,11 @@
const merge = require('webpack-merge');
const {
CleanWebpackPlugin
} = require('clean-webpack-plugin');
const common = require('./webpack.common.js');
module.exports = merge(common, {
plugins: [
new CleanWebpackPlugin()
]
});

514
dist/index.html vendored Normal file
View File

@@ -0,0 +1,514 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Smart Example</title>
<style>
body {
padding: 50px 20px;
}
.title {
text-align: center;
padding: 30px 0;
color: #4acccc;
}
.smart-table {
margin: 50px 0px;
}
</style>
<script type="text/javascript" src="smartUtils.853cd440.js"></script></head>
<body>
<h1 class="title">Smart Table Example</h1>
<!-- smart table example start -->
<div class="smart-table" id="smartTable1">
<table>
<thead>
<tr>
<th colspan="1" rowspan="3" fixed sortable="number">
<div class="cell">Id</div>
</th>
<th colspan="1" rowspan="3" sortable fixed>
<div class="cell">日期</div>
</th>
<th colspan="5" rowspan="1" sortable>
<div class="cell">配送信息</div>
</th>
<th colspan="1" rowspan="3" fixed>
<div class="cell">操作</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="2" sortable>
<div class="cell">姓名</div>
</th>
<th colspan="4" rowspan="1" sortable>
<div class="cell">地址</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="1">
<div class="cell">省份</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">市区</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">地址</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="cell">11</div>
</td>
<td>
<div class="cell">2016-05-02</div>
</td>
<td>
<div class="cell">王小虎2</div>
</td>
<td>
<div class="cell">上海2</div>
</td>
<td>
<div class="cell">普陀区2</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄2</div>
</td>
<td>
<div class="cell">200332</div>
</td>
<td>
<div class="cell"><a href="#">查看2</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">2</div>
</td>
<td>
<div class="cell">2016-05-03</div>
</td>
<td>
<div class="cell">上小虎3</div>
</td>
<td>
<div class="cell">上海3</div>
</td>
<td>
<div class="cell">普陀区3</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄3</div>
</td>
<td>
<div class="cell">200333</div>
</td>
<td>
<div class="cell"><a href="#">查看3</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">小小虎1</div>
</td>
<td>
<div class="cell">上海1</div>
</td>
<td>
<div class="cell">普陀区1</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄1</div>
</td>
<td>
<div class="cell">200331</div>
</td>
<td>
<div class="cell"><a href="#">查看1</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">5</div>
</td>
<td>
<div class="cell">2016-05-04</div>
</td>
<td>
<div class="cell">王小虎4</div>
</td>
<td>
<div class="cell">上海4</div>
</td>
<td>
<div class="cell">普陀区4</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄4</div>
</td>
<td>
<div class="cell">200334</div>
</td>
<td>
<div class="cell"><a href="#">查看4</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">小小虎1</div>
</td>
<td>
<div class="cell">上海1</div>
</td>
<td>
<div class="cell">普陀区1</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄1</div>
</td>
<td>
<div class="cell">200331</div>
</td>
<td>
<div class="cell"><a href="#">查看1</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">5</div>
</td>
<td>
<div class="cell">2016-05-04</div>
</td>
<td>
<div class="cell">王小虎4</div>
</td>
<td>
<div class="cell">上海4</div>
</td>
<td>
<div class="cell">普陀区4</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄4</div>
</td>
<td>
<div class="cell">200334</div>
</td>
<td>
<div class="cell"><a href="#">查看4</a></div>
</td>
</tr>
</tbody>
</table style="width: 100%">
</div>
<!-- smart table example end -->
<!-- smart table example start -->
<div class="smart-table" id="smartTable2">
<table>
<thead>
<tr>
<th colspan="1" rowspan="3" fixed sortable>
<div class="cell">Id</div>
</th>
<th colspan="2" rowspan="1">
<div class="cell">详细</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">配送信息</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="2" sortable>
<div class="cell">日期</div>
</th>
<th colspan="1" rowspan="2">
<div class="cell">姓名</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">地址</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="1">
<div class="cell">省份</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">市区</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">地址</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="cell">12</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">1王小虎</div>
</td>
<td>
<div class="cell">1上海</div>
</td>
<td>
<div class="cell">2普陀区</div>
</td>
<td>
<div class="cell">3上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-02-03</div>
</td>
<td>
<div class="cell">2王小虎</div>
</td>
<td>
<div class="cell">3上海</div>
</td>
<td>
<div class="cell">4普陀区</div>
</td>
<td>
<div class="cell">2上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">14</div>
</td>
<td>
<div class="cell">2016-03-03</div>
</td>
<td>
<div class="cell">3王小虎</div>
</td>
<td>
<div class="cell">4上海</div>
</td>
<td>
<div class="cell">1普陀区</div>
</td>
<td>
<div class="cell">6上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr unsort>
<td>
<div class="cell">15</div>
</td>
<td>
<div class="cell">2016-04-03</div>
</td>
<td>
<div class="cell">5王小虎</div>
</td>
<td>
<div class="cell">6上海</div>
</td>
<td>
<div class="cell">7普陀区</div>
</td>
<td>
<div class="cell">8上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="smart-table" id="smartTable3">
<table>
<thead>
<tr>
<th colspan="1" rowspan="3" fixed sortable>
<div class="cell">Id</div>
</th>
<th colspan="2" rowspan="1">
<div class="cell">详细</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">配送信息</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="2" sortable>
<div class="cell">日期</div>
</th>
<th colspan="1" rowspan="2">
<div class="cell">姓名</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">地址</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="1">
<div class="cell">省份</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">市区</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">地址</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="cell">12</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">1王小虎</div>
</td>
<td>
<div class="cell">1上海</div>
</td>
<td>
<div class="cell">2普陀区</div>
</td>
<td>
<div class="cell">3上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-02-03</div>
</td>
<td>
<div class="cell">2王小虎</div>
</td>
<td>
<div class="cell">3上海</div>
</td>
<td>
<div class="cell">4普陀区</div>
</td>
<td>
<div class="cell">2上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">14</div>
</td>
<td>
<div class="cell">2016-03-03</div>
</td>
<td>
<div class="cell">3王小虎</div>
</td>
<td>
<div class="cell">4上海</div>
</td>
<td>
<div class="cell">1普陀区</div>
</td>
<td>
<div class="cell">6上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr unsort>
<td colspan="5">
<div class="cell">合计</div>
</td>
<td>
<div class="cell">888888</div>
</td>
<td>
<div class="cell">999999</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- smart table example end -->
<script>
new SmartUI.Table({
selector: '#smartTable1',
tableHeight: 300
})
new SmartUI.Table({
selector: '#smartTable2',
tableHeight: function () {
return 300
}
})
new SmartUI.Table({
selector: '#smartTable3'
})
</script>
</body>
</html>

1
dist/smartUtils.853cd440.js vendored Normal file

File diff suppressed because one or more lines are too long

7688
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

28
package.json Normal file
View File

@@ -0,0 +1,28 @@
{
"name": "smart-utils",
"version": "1.0.0",
"description": "smart uitls for ssr",
"main": "index.js",
"scripts": {
"serve": "webpack-dev-server --open --config config/webpack.dev.js",
"build": "webpack --config config/webpack.prod.js"
},
"author": "pyj92055@163.com",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.1",
"extract-text-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.1.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1",
"webpack-merge": "^4.2.2"
},
"dependencies": {},
"keywords": []
}

0
packages/alert/index.js Normal file
View File

14
packages/table/index.js Normal file
View File

@@ -0,0 +1,14 @@
import './index.scss'
import initMixin from './src/core'
function Table(options) {
if (!(this instanceof Table)) {
console.error('Smart Table is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Table)
export default Table

132
packages/table/index.scss Normal file
View File

@@ -0,0 +1,132 @@
.smart-table {
position: relative;
overflow: hidden;
box-sizing: border-box;
flex: 1;
width: 100%;
max-width: 100%;
background-color: #fff;
font-size: 14px;
color: #606266;
border: 1px solid #EBEEF5;
border-right: none;
border-bottom: none;
table {
border-spacing: 0;
border: 0;
}
thead {
color: #909399;
font-weight: 500;
background: #F5F7FA;
}
th {
user-select: none;
overflow: hidden;
&[sortable] {
cursor: pointer;
:after {
margin-left: 5px;
content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAOCAYAAAAbvf3sAAAAAXNSR0IArs4c6QAAAR5JREFUKBVjYKA7+P//P/OBo2dmHzx6rgab5YzIgseOPeb8/e/Vyv8M/33B4owM0+2tjHMYGRn/wdTBNRw7dlXo9/8fm4E2WMEkQTQjA+N6OWmhKEVFxR8QPpA8eOqyLMPvXzuBijVBgugAaMNhPi4mP0NDww8sIMn/f35aMP1nnA00DV0thP+fgeHz93/mQM5O7ArwiIKNPHDkjCMTEwM/HnUM//4zvXSwNjoOdhIzK9O7f7//LQXaLIlNE9DUW+zMjO4gObijjx8/r/Dr79+dQE1qyJoYGRlOcbMzeJuYmLwBiTPBJC0tDR9wczBYgxTAxIDsbUDFjjDFIHG4DTBFFy9e5P7w+c/q/4wML+2tjFKBQfoHJoeTBiUPXJIAbjheeFXAZxsAAAAASUVORK5CYII=');
}
&.desc {
:after {
content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAOCAYAAAAbvf3sAAAAAXNSR0IArs4c6QAAASdJREFUKBVjYKA7+P//P/OBo2dmHzx6rgab5YzIgseOPeb8/e/Vyv8M/33B4owM0+2tjHMYGRn/wdTBNRw7dlXo9/8fm4E2WMEkQTQjA+N6OWmhKEVFxR8QPpA8eOqyLMPvXzuBijVBgugAaMNhPi4mP0NDww8sIMn/f35aMP1nnA00DV0thP+fgeHz93/mQM5O7ArwiIKNdF7435HhHwM/HnUMDEwML/fGMx4HO+kfE8O7//8YljL8Z5DEpomRkeEW+z8Gd5AcE4jYH8t4kYOBwQokAeIjA6DYKR52BusdiYwPQOIovvRd9l/ky0+Grf//M5iBJRkZtvGIMIRu9mX8BuKDAIoGkIDbov/cv/4wrAbKvHRQYEhtcGT8AxLHC0JX/WfGpQAAJIlcYMXwsAoAAAAASUVORK5CYII=');
}
}
&.asc {
:after {
content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAOCAYAAAAbvf3sAAAAAXNSR0IArs4c6QAAARlJREFUKBVjYKA7aPj/n8lx/v+pQFyFzXJGZEHPbf/Zf7xkWPr/P0MwSJyRkWGqfQJDXgMj4z+YOrgGl1X/+f9+Ydj4n4HBHiYJ1bSWQ5whersX408wH0S4Lv8v9ecHw3agyXogPjoAmnqQmYfBf08Y40cWkOSfnww2DIwMS4FOWIquGMb/+5XBGsjeBuMTTYP9cODIGUcmJgZ+fLr+/Wd66WBtdBzsJGZWpnf/fv9bCvSwJDZNQFNvsTMzuoPk4KF0/Ph5hV9//+4EalJD1gT01yludgZvExOTNyBxJpikpaXhA24OBmuQApgYkL0NqNgRphgkDrcBpujixYvcHz7/Wf2fkeGlvZVRKiMj4x+YHE76////zLgkATPDVMggLp6aAAAAAElFTkSuQmCC');
}
}
}
}
td,
th {
padding: 12px 0;
min-width: 50px;
box-sizing: border-box;
text-overflow: ellipsis;
vertical-align: middle;
position: relative;
text-align: left;
border-bottom: 1px solid #EBEEF5;
border-right: 1px solid #EBEEF5;
&.is-hidden>* {
visibility: hidden;
}
}
.cell {
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
word-break: break-all;
line-height: 23px;
padding-right: 10px;
padding-left: 10px;
}
th>.cell {
display: inline-block;
-webkit-box-sizing: border-box;
box-sizing: border-box;
position: relative;
vertical-align: middle;
padding-left: 10px;
padding-right: 10px;
width: 100%;
}
.smart-table_body,
.smart-table_footer,
.smart-table_header {
table-layout: fixed;
border-collapse: separate;
background: #fff;
}
.smart-table_header-wrapper {
overflow: hidden;
}
.smart-table_body-wrapper {
overflow: scroll;
}
.smart-table_fixed,
.smart-table_fixed-right {
position: absolute;
top: 0;
left: 0;
overflow-x: hidden;
overflow-y: hidden;
box-shadow: 0 0 10px rgba(0, 0, 0, .12);
}
.smart-table_fixed-right {
top: 0;
left: auto;
right: 0;
.smart-table_fixed-body-wrapper,
.smart-table_fixed-footer-wrapper,
.smart-table_fixed-header-wrapper {
left: auto;
right: 0;
}
}
.smart-table_fixed-right-patch {
position: absolute;
top: -1px;
right: 0;
background-color: #F5F7FA;
}
.smart-table_fixed-header-wrapper {
position: absolute;
left: 0;
top: 0;
z-index: 3;
}
.smart-table_fixed-body-wrapper {
position: absolute;
left: 0;
top: 37px;
overflow: hidden;
z-index: 3;
}
}

355
packages/table/src/core.js Normal file
View File

@@ -0,0 +1,355 @@
import {
sort
} from './vdom';
import {
createTabelWrapper,
getEmptyIndexInArray,
getIntByAttr,
throttle,
isWindows
} from './utils';
export default function initMixin(Table) {
Table.prototype._init = function (options = {}) {
if (!options.selector) {
console.error("Smart Table init need a selector")
}
const vm = this;
vm.$options = options;
vm.isWindows = isWindows();
vm.scrollHeightFit = vm.isWindows ? 17 : 0;
const root = options.selector && document.querySelector(String(options.selector).trim());
if (!root) return;
const table = root.querySelector("table");
if (!table) return;
const thead = table.querySelector("thead");
const tbody = table.querySelector("tbody");
table.style.width = "100%";
vm.$root = root;
const theadHeight = thead.offsetHeight;
let customHeight = options.tableHeight || 400;
customHeight = typeof customHeight === 'function' ? customHeight() : customHeight;
customHeight = customHeight > theadHeight ? customHeight : (theadHeight + 100);
const tbodyHeight = tbody.offsetHeight;
//获取table宽高
vm.size = {
theadHeight: theadHeight,
tbodyHeight: customHeight - theadHeight,
tabelWidth: table.offsetWidth,
tableHeight: customHeight,
wrapperHeigth: theadHeight + tbodyHeight
}
//初始化thead 并获取props
vm.props = initProps(thead);
//获取colgroup数据数组
vm.colgroup = getColgroup(table);
//根据头部列的二维数组 获取最小表格宽度
vm.size.tabelWidth = table.style.width = vm.colgroup.reduce((total, num) => total + num)
//初始化fixed元素及宽度
initFixed(thead, vm);
//初始化table 拆分table的thead和tbody
vm.$theadWrapper = createTabelWrapper("smart-table_header-wrapper", vm, "header", thead);
vm.$tbodyWrapper = createTabelWrapper("smart-table_body-wrapper", vm, "body", tbody);
root.appendChild(vm.$theadWrapper);
root.appendChild(vm.$tbodyWrapper);
vm.size.theadHeight = thead.offsetHeight;
vm.size.tbodyHeight = customHeight - thead.offsetHeight;
//删除空余的table节点
table.parentNode.removeChild(table);
rollupFixed(vm, thead, tbody)
//获取tbody的data数据
vm.data = initData(vm, tbody);
initSortEvent(vm);
bindEvents(vm);
if (vm.isWindows) {
let th = document.createElement("th");
th.setAttribute("width", "17");
th.setAttribute("rowspan", vm.props.shapes.length);
thead.querySelector("tr").appendChild(th);
}
}
}
function rollupFixed(vm, theadModel, tbodyModel) {
const {
fixedLeft,
fixedRight
} = vm.props;
let rootMinWidth = 320;
vm.$root.querySelectorAll(".smart-table_body-wrapper").forEach(wrapper => {
wrapper.style.height = vm.size.tbodyHeight + "px";
})
//左边有固定列
if (fixedLeft.thead.length > 0) {
rootMinWidth = rootMinWidth > fixedLeft.width ? rootMinWidth : fixedLeft.width;
//构建header
let thead = theadModel.cloneNode(true);
thead.querySelector("tr").querySelectorAll("th").forEach((column, index) => {
if (fixedLeft.thead.indexOf("field-" + index) === -1) {
column.classList.add('is-hidden')
}
})
let headerWrapper = createTabelWrapper("smart-table_fixed-header-wrapper", vm, "header", thead);
//构建body
let tbody = tbodyModel.cloneNode(true);
let rows = tbody.querySelectorAll("tr");
rows.forEach(row => {
row.querySelectorAll("td").forEach((column, index) => {
if (fixedLeft.tbody.indexOf("field-" + index) === -1) {
column.classList.add('is-hidden')
}
})
})
let bodyWrapper = createTabelWrapper("smart-table_fixed-body-wrapper", vm, "body", tbody);
bodyWrapper.style.top = vm.size.theadHeight + "px";
bodyWrapper.style.height = (vm.size.tbodyHeight - vm.scrollHeightFit) + "px";
let fixedContainer = document.createElement("div");
fixedContainer.className = "smart-table_fixed";
fixedContainer.appendChild(headerWrapper);
fixedContainer.appendChild(bodyWrapper);
fixedContainer.style.width = fixedLeft.width + "px";
fixedContainer.style.height = vm.size.wrapperHeigth + "px";
vm.$root.appendChild(fixedContainer);
vm.$fixedLeft = bodyWrapper;
}
//右边有固定列
if (fixedRight.thead.length > 0) {
rootMinWidth = rootMinWidth + fixedRight.width;
//构建header
let thead = theadModel.cloneNode(true);
thead.querySelector("tr").querySelectorAll("th").forEach((column, index) => {
if (fixedRight.thead.indexOf("field-" + index) === -1) {
column.classList.add('is-hidden')
}
})
let headerWrapper = createTabelWrapper("smart-table_fixed-header-wrapper", vm, "header", thead);
//构建body
let tbody = tbodyModel.cloneNode(true);
let rows = tbody.querySelectorAll("tr");
rows.forEach(row => {
row.querySelectorAll("td").forEach((column, index) => {
if (fixedRight.tbody.indexOf("field-" + index) === -1) {
column.classList.add('is-hidden')
}
})
})
let bodyWrapper = createTabelWrapper("smart-table_fixed-body-wrapper", vm, "body", tbody);
bodyWrapper.style.top = vm.size.theadHeight + "px";
bodyWrapper.style.height = (vm.size.tbodyHeight - vm.scrollHeightFit) + "px";
let fixedContainer = document.createElement("div");
fixedContainer.className = "smart-table_fixed-right";
fixedContainer.style.right = vm.scrollHeightFit + "px";
fixedContainer.appendChild(headerWrapper);
fixedContainer.appendChild(bodyWrapper);
fixedContainer.style.width = fixedRight.width + "px";
fixedContainer.style.height = vm.size.wrapperHeigth + "px";
vm.$root.appendChild(fixedContainer);
vm.$fixedRight = bodyWrapper;
if (vm.isWindows) {
let rightPatch = document.createElement("div");
rightPatch.className = "smart-table_fixed-right-patch";
rightPatch.style.width = "17px";
rightPatch.style.height = vm.size.theadHeight + "px";
vm.$root.appendChild(rightPatch)
}
}
vm.$root.style.minWidth = rootMinWidth + "px";
}
//根据表格中的tbody第一行 查出每列的宽度并记录
function getColgroup(table) {
let arr = [];
const columns = table.querySelector("tbody tr").querySelectorAll("td");
columns.forEach(column => {
let width = column.offsetWidth;
if (width < 50) {
width = width + 30;
} else if (width >= 50 && width < 100) {
width = width + 50;
} else {
width = width + 60;
}
arr.push(width)
})
return arr;
}
function bindEvents(vm) {
vm.$tbodyWrapper.addEventListener("scroll", () => syncPostion(vm), {
passive: true
})
// window.addEventListener("resize", function () {
// console.log('resize:::;', vm.$options.selector)
// })
}
function syncPostion(vm) {
throttle(20, () => {
vm.$theadWrapper.scrollLeft = vm.$tbodyWrapper.scrollLeft;
if (vm.$fixedLeft) {
vm.$fixedLeft.scrollTop = vm.$tbodyWrapper.scrollTop;
}
if (vm.$fixedRight) {
vm.$fixedRight.scrollTop = vm.$tbodyWrapper.scrollTop;
}
})()
}
function initSortEvent(vm) {
let els = Array.from(vm.$root.querySelectorAll("th[sortable"));
if (els.length === 0) return;
els.forEach(el => {
el.addEventListener("click", $event => {
$event.stopPropagation();
let sortType = "ASC";
let sortOrder = el.getAttribute("sortable") || "string";
if (el.classList.contains("asc")) {
el.classList.remove("asc");
el.classList.add("desc");
sortType = "DESC"
} else {
el.classList.remove("desc");
el.classList.add("asc");
}
els = els.map(item => {
if (el != item) {
item.classList.remove("asc", "desc")
}
return item
})
sort(vm, el.getAttribute("sortkey"), sortType, sortOrder)
})
})
}
function initProps(thead) {
let props = {};
//创建表头单元格二维数组
let shapes = [];
let rows = thead.querySelectorAll("tr");
rows.forEach((row, index) => {
let shape = shapes[index] || [];
let columns = row.querySelectorAll("th");
columns.forEach((column) => {
let rowspan = getIntByAttr(column, "rowspan", 1);
let colspan = getIntByAttr(column, "colspan", 1);
let insertIndex = getEmptyIndexInArray(shape) || shape.length;
shape[insertIndex] = column;
if (column.hasAttribute("sortable")) {
column.setAttribute("sortkey", "field-" + insertIndex);
}
if (colspan > 1) {
for (let i = 1; i < colspan; i++) {
shape[insertIndex + i] = 0;
}
}
if (rowspan > 1) {
for (let i = 1; i < rowspan; i++) {
let next = shapes[index + i] || [];
for (let j = 0; j < colspan; j++) {
next[insertIndex + j] = 0;
}
shapes[index + i] = next;
}
}
shapes[index] = shape;
})
})
props.shapes = shapes;
return props;
}
function initFixed(thead, vm) {
let {
colgroup,
props
} = vm;
const columnLen = colgroup.length;
let fixedLeft = {
thead: [],
tbody: [],
width: 0
};
let fixedRight = {
thead: [],
tbody: [],
width: 0
};
const columns = thead.querySelector("tr").querySelectorAll("th");
const len = columns.length;
let lastLeftIndex = 0;
if (len !== 0) {
if (columns[0].hasAttribute("fixed")) {
//判断左边固定项 不判断最后一项做为左固定项目
for (let i = 0; i < len - 1; i++) {
if (columns[i].hasAttribute("fixed")) {
lastLeftIndex = i;
fixedLeft.thead.push("field-" + i);
let colspan = getIntByAttr(columns[i], "colspan", 1);
for (let j = 0; j < colspan; j++) {
fixedLeft.tbody.push("field-" + (i + j));
fixedLeft.width = fixedLeft.width + colgroup[i + j];
}
}
}
}
if (columns[len - 1].hasAttribute("fixed")) {
//判断右边边固定项 不判断第一项做为右边固定项目
let rightCnt = 0;
for (let i = len - 1; i > 0; i--) {
if (columns[i].hasAttribute("fixed")) {
//左右固定项目重叠时 跳出
if (i === lastLeftIndex) {
break;
}
fixedRight.thead.push("field-" + i);
let colspan = getIntByAttr(columns[i], "colspan", 1);
for (let j = 0; j < colspan; j++) {
rightCnt++;
fixedRight.tbody.push("field-" + (columnLen - rightCnt))
fixedRight.width = fixedRight.width + colgroup[columnLen - rightCnt];
}
}
}
}
}
props.fixedLeft = fixedLeft;
props.fixedRight = fixedRight;
}
function initData(vm, tbody) {
let fixedLeftRows = vm.$fixedLeft && vm.$fixedLeft.querySelectorAll("tbody tr");
let fixedRightRows = vm.$fixedRight && vm.$fixedRight.querySelectorAll("tbody tr");
let data = [];
tbody.querySelectorAll("tr").forEach((row, index) => {
if (!row.hasAttribute("unsort")) {
let rowData = {
$el: row,
$fixedLeftEl: fixedLeftRows && fixedLeftRows[index],
$fixedRightEl: fixedRightRows && fixedRightRows[index],
$key: '$$rowkey' + index
};
row.querySelectorAll("td .cell").forEach((cell, index) => {
rowData["field-" + index] = cell.innerHTML;
})
data.push(rowData)
}
})
return data;
}

View File

@@ -0,0 +1,80 @@
export function createTabelWrapper(className, vm, type, content) {
let wrapper = document.createElement("div");
wrapper.className = className;
let table = document.createElement("table");
table.className = "smart-table_" + type;
table.style.width = vm.size.tabelWidth + "px";
table.appendChild(createColgroup(vm.colgroup));
table.appendChild(content);
wrapper.appendChild(table);
return wrapper;
}
export function getIntByAttr(el, key, def) {
return Number.parseInt(el.getAttribute(key) || def)
}
export function getEmptyIndexInArray(array) {
for (let i = 0, len = array.length; i < len; i++) {
if (array[i] === undefined) {
return i
}
}
}
export function throttle(delay, callback) {
let timeoutID;
let lastExec = 0;
function wrapper() {
let self = this;
let elapsed = new Date().getTime() - lastExec;
let args = arguments;
function exec() {
lastExec = new Date().getTime();
callback.apply(self, args)
}
function clear() {
timeoutID = undefined;
}
if (timeoutID) {
clearTimeout(timeoutID)
}
if (elapsed > delay) {
exec()
} else {
timeoutID = setTimeout(exec, delay - elapsed)
}
}
return wrapper;
}
export function isWindows() {
var agent = navigator.userAgent.toLowerCase();
if (agent.indexOf("win32") >= 0 || agent.indexOf("wow32") >= 0) {
return true;
}
if (agent.indexOf("win64") >= 0 || agent.indexOf("wow64") >= 0) {
return true;
}
return false;
}
//创建colgroup节点
function createColgroup(arr) {
if (!arr) return;
let colgroup = document.createElement("colgroup");
arr.forEach(item => {
let col = document.createElement("col");
col.setAttribute("width", item);
colgroup.appendChild(col)
})
return colgroup;
}

View File

@@ -0,0 +1,75 @@
export function sort(vm, key, sortType, sortOrder) {
if (!vm.data || vm.data.length < 1) return;
//使用快速排序
let vnode = quickSort(JSON.parse(JSON.stringify(vm.data)), key, sortType, sortOrder);
//判断顺序是否改变过
if (JSON.stringify(vm.data) !== JSON.stringify(vnode)) {
//计算需要更新的最小路径,并移动元素
diff(vm.data, vnode);
//更新为新的data
vm.data = vnode;
}
}
function diff(oldVnode, vnode) {
let lastIndex = 0;
for (let i = 0; i < vnode.length; i++) {
const nextVNode = vnode[i];
let j = 0;
for (j; j < oldVnode.length; j++) {
const prevVNode = oldVnode[j];
if (nextVNode.$key === prevVNode.$key) {
nextVNode.$el = prevVNode.$el;
nextVNode.$fixedLeftEl = prevVNode.$fixedLeftEl;
nextVNode.$fixedRightEl = prevVNode.$fixedRightEl;
if (j < lastIndex) {
//需要移动
const lastNextVNode = vnode[i - 1];
const refNode = lastNextVNode.$el.nextSibling;
refNode.parentNode.insertBefore(prevVNode.$el, refNode);
if (lastNextVNode.$fixedLeftEl) {
const refLeftNode = lastNextVNode.$fixedLeftEl.nextSibling;
refLeftNode.parentNode.insertBefore(prevVNode.$fixedLeftEl, refLeftNode);
}
if (lastNextVNode.$fixedRightEl) {
const refRightNode = lastNextVNode.$fixedRightEl.nextSibling;
refRightNode.parentNode.insertBefore(prevVNode.$fixedRightEl, refRightNode);
}
} else {
lastIndex = j;
}
break;
}
}
}
}
function quickSort(arr, key, sortType, sortOrder) {
if (arr.length <= 1) {
return arr
}
let left = [],
right = [];
let len = arr.length;
let pivotIndex = Math.floor(len / 2);
let pivot = arr.splice(pivotIndex, 1)[0];
for (let i = 0; i < len - 1; i++) {
if (compare(arr[i][key], pivot[key], sortType, sortOrder)) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return quickSort(left, key, sortType, sortOrder).concat(pivot, quickSort(right, key, sortType, sortOrder));
}
function compare(key1, key2, sortType, sortOrder) {
if (sortOrder === "number") {
key1 = parseFloat(key1);
key2 = parseFloat(key2);
}
return sortType === 'ASC' ? key1 < key2 : key1 > key2;
}

514
public/index.html Normal file
View File

@@ -0,0 +1,514 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Smart Example</title>
<style>
body {
padding: 50px 20px;
}
.title {
text-align: center;
padding: 30px 0;
color: #4acccc;
}
.smart-table {
margin: 50px 0px;
}
</style>
</head>
<body>
<h1 class="title">Smart Table Example</h1>
<!-- smart table example start -->
<div class="smart-table" id="smartTable1">
<table>
<thead>
<tr>
<th colspan="1" rowspan="3" fixed sortable="number">
<div class="cell">Id</div>
</th>
<th colspan="1" rowspan="3" sortable fixed>
<div class="cell">日期</div>
</th>
<th colspan="5" rowspan="1" sortable>
<div class="cell">配送信息</div>
</th>
<th colspan="1" rowspan="3" fixed>
<div class="cell">操作</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="2" sortable>
<div class="cell">姓名</div>
</th>
<th colspan="4" rowspan="1" sortable>
<div class="cell">地址</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="1">
<div class="cell">省份</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">市区</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">地址</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="cell">11</div>
</td>
<td>
<div class="cell">2016-05-02</div>
</td>
<td>
<div class="cell">王小虎2</div>
</td>
<td>
<div class="cell">上海2</div>
</td>
<td>
<div class="cell">普陀区2</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄2</div>
</td>
<td>
<div class="cell">200332</div>
</td>
<td>
<div class="cell"><a href="#">查看2</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">2</div>
</td>
<td>
<div class="cell">2016-05-03</div>
</td>
<td>
<div class="cell">上小虎3</div>
</td>
<td>
<div class="cell">上海3</div>
</td>
<td>
<div class="cell">普陀区3</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄3</div>
</td>
<td>
<div class="cell">200333</div>
</td>
<td>
<div class="cell"><a href="#">查看3</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">小小虎1</div>
</td>
<td>
<div class="cell">上海1</div>
</td>
<td>
<div class="cell">普陀区1</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄1</div>
</td>
<td>
<div class="cell">200331</div>
</td>
<td>
<div class="cell"><a href="#">查看1</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">5</div>
</td>
<td>
<div class="cell">2016-05-04</div>
</td>
<td>
<div class="cell">王小虎4</div>
</td>
<td>
<div class="cell">上海4</div>
</td>
<td>
<div class="cell">普陀区4</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄4</div>
</td>
<td>
<div class="cell">200334</div>
</td>
<td>
<div class="cell"><a href="#">查看4</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">小小虎1</div>
</td>
<td>
<div class="cell">上海1</div>
</td>
<td>
<div class="cell">普陀区1</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄1</div>
</td>
<td>
<div class="cell">200331</div>
</td>
<td>
<div class="cell"><a href="#">查看1</a></div>
</td>
</tr>
<tr>
<td>
<div class="cell">5</div>
</td>
<td>
<div class="cell">2016-05-04</div>
</td>
<td>
<div class="cell">王小虎4</div>
</td>
<td>
<div class="cell">上海4</div>
</td>
<td>
<div class="cell">普陀区4</div>
</td>
<td>
<div class="cell">上海市普陀区金沙江路 1518 弄4</div>
</td>
<td>
<div class="cell">200334</div>
</td>
<td>
<div class="cell"><a href="#">查看4</a></div>
</td>
</tr>
</tbody>
</table style="width: 100%">
</div>
<!-- smart table example end -->
<!-- smart table example start -->
<div class="smart-table" id="smartTable2">
<table>
<thead>
<tr>
<th colspan="1" rowspan="3" fixed sortable>
<div class="cell">Id</div>
</th>
<th colspan="2" rowspan="1">
<div class="cell">详细</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">配送信息</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="2" sortable>
<div class="cell">日期</div>
</th>
<th colspan="1" rowspan="2">
<div class="cell">姓名</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">地址</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="1">
<div class="cell">省份</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">市区</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">地址</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="cell">12</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">1王小虎</div>
</td>
<td>
<div class="cell">1上海</div>
</td>
<td>
<div class="cell">2普陀区</div>
</td>
<td>
<div class="cell">3上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-02-03</div>
</td>
<td>
<div class="cell">2王小虎</div>
</td>
<td>
<div class="cell">3上海</div>
</td>
<td>
<div class="cell">4普陀区</div>
</td>
<td>
<div class="cell">2上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">14</div>
</td>
<td>
<div class="cell">2016-03-03</div>
</td>
<td>
<div class="cell">3王小虎</div>
</td>
<td>
<div class="cell">4上海</div>
</td>
<td>
<div class="cell">1普陀区</div>
</td>
<td>
<div class="cell">6上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr unsort>
<td>
<div class="cell">15</div>
</td>
<td>
<div class="cell">2016-04-03</div>
</td>
<td>
<div class="cell">5王小虎</div>
</td>
<td>
<div class="cell">6上海</div>
</td>
<td>
<div class="cell">7普陀区</div>
</td>
<td>
<div class="cell">8上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="smart-table" id="smartTable3">
<table>
<thead>
<tr>
<th colspan="1" rowspan="3" fixed sortable>
<div class="cell">Id</div>
</th>
<th colspan="2" rowspan="1">
<div class="cell">详细</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">配送信息</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="2" sortable>
<div class="cell">日期</div>
</th>
<th colspan="1" rowspan="2">
<div class="cell">姓名</div>
</th>
<th colspan="4" rowspan="1">
<div class="cell">地址</div>
</th>
</tr>
<tr>
<th colspan="1" rowspan="1">
<div class="cell">省份</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">市区</div>
</th>
<th colspan="1" rowspan="1">
<div class="cell">地址</div>
</th>
<th colspan="1" rowspan="1" sortable>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="cell">12</div>
</td>
<td>
<div class="cell">2016-01-03</div>
</td>
<td>
<div class="cell">1王小虎</div>
</td>
<td>
<div class="cell">1上海</div>
</td>
<td>
<div class="cell">2普陀区</div>
</td>
<td>
<div class="cell">3上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">13</div>
</td>
<td>
<div class="cell">2016-02-03</div>
</td>
<td>
<div class="cell">2王小虎</div>
</td>
<td>
<div class="cell">3上海</div>
</td>
<td>
<div class="cell">4普陀区</div>
</td>
<td>
<div class="cell">2上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr>
<td>
<div class="cell">14</div>
</td>
<td>
<div class="cell">2016-03-03</div>
</td>
<td>
<div class="cell">3王小虎</div>
</td>
<td>
<div class="cell">4上海</div>
</td>
<td>
<div class="cell">1普陀区</div>
</td>
<td>
<div class="cell">6上海市普陀区金沙江路 1518 弄</div>
</td>
<td>
<div class="cell">200331</div>
</td>
</tr>
<tr unsort>
<td colspan="5">
<div class="cell">合计</div>
</td>
<td>
<div class="cell">888888</div>
</td>
<td>
<div class="cell">999999</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- smart table example end -->
<script>
new SmartUI.Table({
selector: '#smartTable1',
tableHeight: 300
})
new SmartUI.Table({
selector: '#smartTable2',
tableHeight: function () {
return 300
}
})
new SmartUI.Table({
selector: '#smartTable3'
})
</script>
</body>
</html>

5
src/index.js Normal file
View File

@@ -0,0 +1,5 @@
import Table from '../packages/table'
window.SmartUI = {
Table
}