@wiajs/ui
Version:
wia app ui packages
178 lines (177 loc) • 7.41 kB
JavaScript
import { Utils, Event } from '@wiajs/core';
const def = {
selector: '.data-table',
domProp: 'wiaTable',
name: 'wiaTable'
};
/**
* 从F7 DataTable迁移,与app和自动化创建脱离,标准手动方式创建
* DataTable 扩展了Table,实现动态表格生成
* 为已具备html的数据表格提供样式变化功能
* 动态生成表格,需在生成后创建该组件
*/ export default class Table extends Event {
constructor(page, opt = {}){
super(opt, [
page
]), this.name = '' // table name
;
const m = this;
this.page = page;
this.opt = {
...def,
...opt
};
this.name = this.opt.name;
// 容器
const $el = opt.el || page.view.find(this.opt.selector);
if ($el.length === 0) return undefined;
m.$el = $el;
m.el = $el[0];
// 已创建,直接返回
if (m.el[this.opt.domProp]) {
const instance = m.el[this.opt.domProp];
m.destroy();
return instance;
}
m.el[this.opt.domProp] = m;
const header = $el.find('.data-table-header');
Utils.extend(m, {
collapsible: $el.hasClass('data-table-collapsible'),
// Headers
$headerEl: header,
$headerSelectedEl: $el.find('.data-table-header-selected')
});
// Events
function handleChange(e) {
// 代码更改checkbox属性,不会触发change,代码触发change,这里需排除,避免循环
if (e.detail && e.detail.sentByWiaF7Table) {
// Scripted event, don't do anything
return;
}
// this 为被选中的input
const $inputEl = $(this);
// 是否被选中
const { checked } = $inputEl[0];
// 列数
const columnIndex = $inputEl.parents('td,th').index();
// 表头 checkbox选择影响当页所有行,排除模板行
if ($inputEl.parents('thead').length > 0) {
// 行首,选择行
if (columnIndex === 0) $el.find(`tbody tr:not([name="${m.name}-tp"])`)[checked ? 'addClass' : 'removeClass']('data-table-row-selected');
// 全选或取消全选,更新每行checkbox,并触发 change事件
$el.find(`tbody tr:not([name="${m.name}-tp"]) td:nth-child(${columnIndex + 1}) input`).prop('checked', checked).trigger('change', {
sentByWiaF7Table: true
});
$inputEl.prop('indeterminate', false);
} else {
// 表体checkbox
if (columnIndex === 0) $inputEl.parents('tr')[checked ? 'addClass' : 'removeClass']('data-table-row-selected');
m.headerCheck(columnIndex);
}
// 延迟到change事件后触发,避免统计选择行数据差错
m.headerSel();
}
function handleSortableClick() {
const $cellEl = $(this);
const isActive = $cellEl.hasClass('sortable-cell-active');
const currentSort = $cellEl.hasClass('sortable-desc') ? 'desc' : 'asc';
let newSort;
if (isActive) {
newSort = currentSort === 'desc' ? 'asc' : 'desc';
$cellEl.removeClass('sortable-desc sortable-asc').addClass(`sortable-${newSort}`);
} else {
$el.find('thead .sortable-cell-active').removeClass('sortable-cell-active');
$cellEl.addClass('sortable-cell-active');
newSort = currentSort;
}
$cellEl.trigger('datatable:sort', newSort);
m.emit('local::sort dataTableSort', $cellEl, newSort === 'desc');
}
m.attachEvents = function() {
m.$el.on('change', '.checkbox-cell input[type="checkbox"]', handleChange);
m.$el.find('thead .sortable-cell').on('click', handleSortableClick);
};
m.detachEvents = function() {
m.$el.off('change', '.checkbox-cell input[type="checkbox"]', handleChange);
m.$el.find('thead .sortable-cell').off('click', handleSortableClick);
};
// Init
m.init();
}
setCollapsibleLabels() {
const m = this;
if (!m.collapsible) return;
m.$el.find('tbody td:not(.checkbox-cell)').each((index, el)=>{
const $el = $(el);
const elIndex = $el.index();
const collpsibleTitle = $el.attr('data-collapsible-title');
if (!collpsibleTitle && collpsibleTitle !== '') {
$el.attr('data-collapsible-title', m.$el.find('thead th').eq(elIndex).text());
}
});
}
/**
* 表头选择区域显示切换,统计选择行,触发选择改变事件,方便跨页统计
*/ headerSel() {
const m = this;
// 选中行
// const rs = m.$el.find('tbody .checkbox-cell input:checked');
const rs = m.$el.find('.data-table-row-selected');
const len = rs.length;
// 改变表头操作面板
if (m.$headerEl.length > 0 && m.$headerSelectedEl.length > 0) {
if (len && !m.$el.hasClass('data-table-has-checked')) m.$el.addClass('data-table-has-checked');
else if (!len && m.$el.hasClass('data-table-has-checked')) m.$el.removeClass('data-table-has-checked');
// 选中数量,跨行选择数量与当前也选择数量不一致
m.$headerSelectedEl.find('.data-table-selected-count').text(len);
}
// 触发当前表选择事件,参数为选择行
// 延迟到change事件后触发,避免跨页统计选择行数据差错
setTimeout(()=>{
m.emit('local::select', rs);
}, 10);
}
/**
* 根据行选择,选中或取消表头checkbox
*/ headerCheck(col = 0) {
const { $el } = this;
// 表头checkbox
const ckb = $el.findNode(`thead .checkbox-cell:nth-child(${col + 1}) input[type="checkbox"]`);
if (ckb.length) {
const checkedRows = $el.find(`tbody .checkbox-cell:nth-child(${col + 1}) input[type="checkbox"]:checked`).length;
// 排除模板行
const totalRows = $el.find(`tbody tr:not([name="${this.name}-tp"])`).length;
if (checkedRows === 0) ckb.prop('checked', false);
else if (checkedRows === totalRows) {
const ck = ckb.dom.checked;
// 全选
if (!ck) {
ckb.prop('checked', true);
ckb.trigger('change', {
sentByWiaF7Table: true
});
}
}
ckb.prop('indeterminate', checkedRows > 0 && checkedRows < totalRows) // 部分选中
;
}
}
init() {
const m = this;
m.attachEvents();
m.setCollapsibleLabels();
m.headerSel();
}
destroy() {
let m = this;
m.$el.trigger('datatable:beforedestroy');
m.emit('local::beforeDestroy dataTableBeforeDestroy', m);
m.detachEvents();
if (m.$el[0]) {
m.$el[0].f7DataTable = null;
delete m.$el[0].f7DataTable;
}
Utils.deleteProps(m);
m = null;
}
}