Comparing version 0.3.6 to 0.4.0
1997
dist/datagrid.js
@@ -1,1293 +0,794 @@ | ||
(function webpackUniversalModuleDefinition(root, factory) { | ||
if(typeof exports === 'object' && typeof module === 'object') | ||
module.exports = factory(); | ||
else if(typeof define === 'function' && define.amd) | ||
define([], factory); | ||
else if(typeof exports === 'object') | ||
exports["Datagrid"] = factory(); | ||
else | ||
root["Datagrid"] = factory(); | ||
})(this, function() { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
/******/ // The module cache | ||
/******/ var installedModules = {}; | ||
/*! | ||
* datagrid v0.4.0 | ||
* https://github.com/lmk123/datagrid | ||
* Released under the MIT License. | ||
*/ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(factory((global.datagrid = {}))); | ||
}(this, (function (exports) { 'use strict'; | ||
/******/ // The require function | ||
/******/ function __webpack_require__(moduleId) { | ||
function __$styleInject(css, returnValue) { | ||
if (typeof document === 'undefined') { | ||
return returnValue; | ||
} | ||
css = css || ''; | ||
var head = document.head || document.getElementsByTagName('head')[0]; | ||
var style = document.createElement('style'); | ||
style.type = 'text/css'; | ||
head.appendChild(style); | ||
if (style.styleSheet){ | ||
style.styleSheet.cssText = css; | ||
} else { | ||
style.appendChild(document.createTextNode(css)); | ||
} | ||
return returnValue; | ||
} | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ return installedModules[moduleId].exports; | ||
/*! | ||
* tinyemitter.js v1.0.1 | ||
* https://github.com/lmk123/tinyemitter | ||
* Released under the MIT License. | ||
*/ | ||
var TinyEmitter = /** @class */ (function () { | ||
function TinyEmitter() { | ||
this.e = {}; | ||
} | ||
TinyEmitter.prototype.on = function (name, handle) { | ||
var e = this.e; | ||
(e[name] || (e[name] = [])).push(handle); | ||
}; | ||
TinyEmitter.prototype.off = function (name, handle) { | ||
var e = this.e; | ||
if (!handle) { | ||
delete e[name]; | ||
return; | ||
} | ||
var events = e[name]; | ||
if (!events) | ||
{ return; } | ||
var i = events.indexOf(handle); | ||
if (i >= 0) { | ||
if (events.length === 1) { | ||
delete e[name]; | ||
} | ||
else { | ||
// 使用新数组替代原本的数组, | ||
// 这是为了避免在回调函数内调用 off 方法时改变了数组导致前面的回调函数被跳过 | ||
e[name] = events.filter(function (h) { return h !== handle; }); | ||
} | ||
} | ||
}; | ||
TinyEmitter.prototype.emit = function (name) { | ||
var arguments$1 = arguments; | ||
/******/ // Create a new module (and put it into the cache) | ||
/******/ var module = installedModules[moduleId] = { | ||
/******/ exports: {}, | ||
/******/ id: moduleId, | ||
/******/ loaded: false | ||
/******/ }; | ||
var args = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
args[_i - 1] = arguments$1[_i]; | ||
} | ||
var events = this.e[name]; | ||
if (!events) | ||
{ return; } | ||
events.forEach(function (handle) { | ||
handle.apply(null, args); | ||
}); | ||
}; | ||
return TinyEmitter; | ||
}()); | ||
/******/ // Execute the module function | ||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | ||
var template = "<div class=scroll-container><table><thead><tr></tr></thead><tbody></tbody></table></div><div class=modal><div class=modal-content></div></div>"; | ||
/******/ // Flag the module as loaded | ||
/******/ module.loaded = true; | ||
__$styleInject(".datagrid{position:relative}.datagrid .modal{display:none;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;position:absolute;top:0;left:0;right:0;bottom:0;background-color:#fff}.datagrid.show-modal .modal{display:-webkit-box;display:-ms-flexbox;display:flex}.datagrid .scroll-container{height:100%;overflow:scroll}.datagrid table{min-width:100%;border-collapse:collapse;border-spacing:0}.datagrid td{word-wrap:break-word;word-break:break-all}",undefined); | ||
/******/ // Return the exports of the module | ||
/******/ return module.exports; | ||
/******/ } | ||
/** | ||
* @fileOverview 输出一个最基本的、仅包含核心功能的表格类。 | ||
*/ | ||
function defaultThRenderer(column) { | ||
return column.key; | ||
} | ||
function defaultTdRenderer(column, row) { | ||
return row[column.key]; | ||
} | ||
/** | ||
* 根据内容的类型选择不同的方式填充节点。 | ||
* @param node 需要填充的节点。 | ||
* @param content 内容可以是字符串或者一个节点。如果有多个节点,可以传入一个 Fragment 对象。 | ||
*/ | ||
function fillNode(node, content) { | ||
if (typeof content === 'string') { | ||
node.innerHTML = content; | ||
} | ||
else { | ||
node.appendChild(content); | ||
} | ||
} | ||
var fragment = document.createDocumentFragment(); | ||
// 下面的一些 protected 关键字是因为一个 bug 才被注释掉的, | ||
// @see https://github.com/Microsoft/TypeScript/issues/17744 | ||
var BaseGrid = (function (TinyEmitter$$1) { | ||
function BaseGrid(options) { | ||
if ( options === void 0 ) options = {}; | ||
TinyEmitter$$1.call(this); | ||
/* tslint:disable:member-ordering */ | ||
this.el = document.createElement('div'); | ||
/* protected */ this.ui = {}; | ||
this.options = Object.assign({ | ||
td: defaultTdRenderer, | ||
th: defaultThRenderer | ||
}, options); | ||
this.parent = options && options.parent; | ||
var ref = this; | ||
var el = ref.el; | ||
el.className = 'datagrid'; | ||
el.innerHTML = template; | ||
var thead = el.getElementsByTagName('thead')[0]; | ||
Object.assign(this.ui, { | ||
scrollContainer: el.getElementsByClassName('scroll-container')[0], | ||
table: el.getElementsByTagName('table')[0], | ||
thead: thead, | ||
theadRow: thead.firstElementChild, | ||
tbody: el.getElementsByTagName('tbody')[0], | ||
modal: el.getElementsByClassName('modal-content')[0] | ||
}); | ||
} | ||
/******/ // expose the modules object (__webpack_modules__) | ||
/******/ __webpack_require__.m = modules; | ||
if ( TinyEmitter$$1 ) BaseGrid.__proto__ = TinyEmitter$$1; | ||
BaseGrid.prototype = Object.create( TinyEmitter$$1 && TinyEmitter$$1.prototype ); | ||
BaseGrid.prototype.constructor = BaseGrid; | ||
/** 根据数据生成表格内容。 */ | ||
BaseGrid.prototype.setData = function setData (data) { | ||
var this$1 = this; | ||
/******/ // expose the module cache | ||
/******/ __webpack_require__.c = installedModules; | ||
var columns = data.columns; if ( columns === void 0 ) columns = []; | ||
var rows = data.rows; if ( rows === void 0 ) rows = []; | ||
this.curData = { | ||
columns: columns, | ||
rows: rows | ||
}; | ||
var ref = this.ui; | ||
var theadRow = ref.theadRow; | ||
var tbody = ref.tbody; | ||
// 首先重新渲染表头 | ||
if (columns.length) { | ||
columns.forEach(function (column, index) { | ||
if (typeof column === 'string') { | ||
column = { | ||
key: column | ||
}; | ||
} | ||
var th = document.createElement('th'); | ||
fillNode(th, this$1.options.th(column, index)); | ||
this$1.emit('after th render', th, column, index); | ||
fragment.appendChild(th); | ||
}); | ||
theadRow.textContent = ''; | ||
theadRow.appendChild(fragment); | ||
} | ||
else { | ||
theadRow.textContent = ''; | ||
} | ||
// 然后渲染表格 | ||
if (rows.length) { | ||
rows.forEach(function (row, rowIndex) { | ||
var tr = document.createElement('tr'); | ||
columns.forEach(function (column, columnIndex) { | ||
if (typeof column === 'string') { | ||
column = { | ||
key: column | ||
}; | ||
} | ||
var td = document.createElement('td'); | ||
fillNode(td, this$1.options.td(column, row, columnIndex, rowIndex)); | ||
this$1.emit('after td render', td, column, row, rowIndex, columnIndex); | ||
tr.appendChild(td); | ||
}); | ||
fragment.appendChild(tr); | ||
}); | ||
tbody.textContent = ''; | ||
tbody.appendChild(fragment); | ||
this.hideModal(); | ||
} | ||
else { | ||
tbody.textContent = ''; | ||
this.showModal(); | ||
} | ||
}; | ||
/** 显示一段消息。默认会显示“暂无数据” */ | ||
BaseGrid.prototype.showModal = function showModal (html) { | ||
if ( html === void 0 ) html = '暂无数据'; | ||
/******/ // __webpack_public_path__ | ||
/******/ __webpack_require__.p = ""; | ||
this.ui.modal.innerHTML = html; | ||
this.el.classList.add('show-modal'); | ||
}; | ||
/** 隐藏消息。 */ | ||
BaseGrid.prototype.hideModal = function hideModal () { | ||
this.el.classList.remove('show-modal'); | ||
}; | ||
/** | ||
* 销毁对象。 | ||
* @param remove 如果为 true,则从 DOM 中删除元素。 | ||
*/ | ||
BaseGrid.prototype.destroy = function destroy (remove) { | ||
if (remove) { | ||
var ref = this; | ||
var el = ref.el; | ||
var parentElement = el.parentElement; | ||
if (parentElement) { | ||
parentElement.removeChild(el); | ||
} | ||
} | ||
}; | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(0); | ||
/******/ }) | ||
/************************************************************************/ | ||
/******/ ([ | ||
/* 0 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
return BaseGrid; | ||
}(TinyEmitter)); | ||
module.exports = __webpack_require__(1) | ||
module.exports.Selection = __webpack_require__(12) | ||
module.exports.Paging = __webpack_require__(15) | ||
module.exports.Sorting = __webpack_require__(19) | ||
module.exports.ColumnMove = __webpack_require__(22) | ||
module.exports.ColumnFixed = __webpack_require__(25) | ||
/** | ||
* 在事件目标上注册一个事件,并返回取消事件的函数。 | ||
* @param target 事件目标 | ||
* @param event 事件名称 | ||
* @param handler 事件处理函数 | ||
*/ | ||
var addEvent = function (target, event, handler) { | ||
target.addEventListener(event, handler); | ||
return function () { | ||
target.removeEventListener(event, handler); | ||
}; | ||
}; | ||
// https://caniuse.com/#feat=requestanimationframe | ||
var raf = window.requestAnimationFrame || | ||
window.webkitRequestAnimationFrame || | ||
// @ts-ignore | ||
window.mozRequestAnimationFrame || | ||
function (cb) { | ||
setTimeout(cb, 1000 / 60); | ||
}; | ||
/** | ||
* 返回一个基于 requestAnimationFrame 的节流函数。 | ||
* @param cb 要执行的函数 | ||
* @see https://css-tricks.com/debouncing-throttling-explained-examples/#article-header-id-7 | ||
*/ | ||
var rafThrottle = function (cb) { | ||
var running = false; | ||
return function () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
/***/ }, | ||
/* 1 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
if (!running) { | ||
running = true; | ||
raf(function () { | ||
cb.apply(null, args); | ||
running = false; | ||
}); | ||
} | ||
}; | ||
}; | ||
__webpack_require__(2) | ||
var containerTemplate = __webpack_require__(6) | ||
var Event = __webpack_require__(7) | ||
var addEvent = __webpack_require__(8) | ||
var extend = __webpack_require__(9) | ||
var findParent = __webpack_require__(10) | ||
var debounce = __webpack_require__(11) | ||
/** 默认情况下使用 join 将参数转换成一个字符串作为唯一的缓存键 */ | ||
function generate(args) { | ||
return args.join(); | ||
} | ||
/** | ||
* 返回一个能记住函数返回值的函数,避免重复计算 | ||
* @param fn 执行计算的函数 | ||
* @param generateKey 根据函数参数计算唯一的缓存键的函数 | ||
*/ | ||
var memory = function (fn, generateKey) { | ||
if ( generateKey === void 0 ) generateKey = generate; | ||
var DefaultWidth = 100 | ||
var CssClassNamespace = 'data-grid' | ||
var caches = {}; | ||
return function () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
function defaultThRenderer (columnDef) { | ||
return columnDef.name | ||
} | ||
var cacheKey = generateKey(args); | ||
return caches[cacheKey] || (caches[cacheKey] = fn.apply(null, args)); | ||
}; | ||
}; | ||
function defaultTdRenderer (columnDef, rowData) { | ||
return rowData[columnDef.key] | ||
} | ||
var ref = document.createElement('div'); | ||
var style$1 = ref.style; | ||
var vd; | ||
/** | ||
* 获取一个 CSS 属性在当前浏览器中可用的名字。 | ||
* @param property 属性的标准名称。 | ||
*/ | ||
var getCSSProperty = memory(function (property) { | ||
if (property in style$1) | ||
{ return property; } | ||
var camelCase = property[0].toUpperCase() + property.slice(1); | ||
var getVendorProperty = function (vendor) { | ||
var vendorProperty = (vendor + camelCase); | ||
if (vendorProperty in style$1) { | ||
return vendorProperty; | ||
} | ||
}; | ||
if (vd) { | ||
return getVendorProperty(vd); | ||
} | ||
var result; | ||
['webkit', 'ms', 'moz', 'o'].some(function (vendor) { | ||
var vendorProperty = getVendorProperty(vendor); | ||
if (vendorProperty) { | ||
result = vendorProperty; | ||
vd = vendor; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
return result; | ||
}); | ||
var hooks = [] | ||
__$styleInject(".datagrid .fixed-header{position:absolute;top:0;left:0;right:0;background-color:#fff;overflow:hidden}",undefined); | ||
/** | ||
* 构造函数 | ||
* @param {HTMLElement} ele | ||
* @param {Object} [options] | ||
*/ | ||
function DataGrid (ele, options) { | ||
Event.call(this) | ||
var el = this.el = document.createElement('div') | ||
this.options = extend({}, { | ||
height: ele.offsetHeight // 表格的总高度 | ||
}, options) | ||
var fixedHeader = function (Base) { | ||
return (function (Base) { | ||
function anonymous() { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
if (true) { | ||
if (!ele.parentElement) { | ||
throw new Error('Element must have a parentElement') | ||
} | ||
} | ||
Base.apply(this, args); | ||
this.fixedTHead = document.createElement('thead'); | ||
this.fixedTheadRow = document.createElement('tr'); | ||
this.fixedHeaderTable = document.createElement('table'); | ||
this.colGroup = document.createElement('colgroup'); | ||
this.unbindEvents = []; | ||
var ref = this; | ||
var el = ref.el; | ||
var ui = ref.ui; | ||
ui.thead.style.visibility = 'hidden'; | ||
// 创建一个包含表头的 div,通过 CSS 固定在滚动区域上方 | ||
var fixedHeaderWrapper = document.createElement('div'); | ||
fixedHeaderWrapper.className = 'fixed-header'; | ||
// 创建一个仅包含 thead 的表格作为固定表头 | ||
// 使用 colgroup 保持原本的表格与固定表头的单元格宽度一致 | ||
var ref$1 = this; | ||
var fixedHeaderTable = ref$1.fixedHeaderTable; | ||
var colGroup = ref$1.colGroup; | ||
var fixedTHead = ref$1.fixedTHead; | ||
var fixedTheadRow = ref$1.fixedTheadRow; | ||
ui.fixedThead = fixedTHead; | ||
ui.fixedTheadRow = fixedTheadRow; | ||
fixedHeaderTable.appendChild(colGroup); | ||
fixedTHead.appendChild(fixedTheadRow); | ||
fixedHeaderTable.appendChild(fixedTHead); | ||
fixedHeaderWrapper.appendChild(fixedHeaderTable); | ||
el.appendChild(fixedHeaderWrapper); | ||
if (!this.parent) { | ||
var scrollContainer = ui.scrollContainer; | ||
this.unbindEvents.push( | ||
// 窗口大小变化后重新同步表格的宽度 | ||
// TODO: 窗口大小变化后表格的宽度似乎没有变化? | ||
// addEvent( | ||
// window, | ||
// 'resize', | ||
// rafThrottle(() => { | ||
// this.syncFixedHeader() | ||
// }) | ||
// ), | ||
// 表格滚动时,使用 transform 移动固定表头的位置以获得更平滑的效果 | ||
addEvent(scrollContainer, 'scroll', rafThrottle(function () { | ||
// 使用 transform 会比同步 scrollLeft 流畅很多 | ||
fixedHeaderTable.style[ | ||
// @ts-ignore | ||
getCSSProperty('transform')] = "translate3d(-" + (scrollContainer.scrollLeft) + "px,0,0)"; | ||
}))); | ||
} | ||
} | ||
// 从 document 里删除原本的节点并保存下来,供实例销毁之后重新显示出来 | ||
this.origin = ele.parentElement.replaceChild(el, ele) | ||
if ( Base ) anonymous.__proto__ = Base; | ||
anonymous.prototype = Object.create( Base && Base.prototype ); | ||
anonymous.prototype.constructor = anonymous; | ||
/** 同步表头中单元格的宽度。 */ | ||
anonymous.prototype.syncFixedHeader = function syncFixedHeader () { | ||
var ref = this.ui; | ||
var table = ref.table; | ||
var theadRow = ref.theadRow; | ||
this.colGroup.innerHTML = Array.prototype.reduce.call(theadRow.children, function (result, th) { | ||
return (result += "<col width=\"" + (th.offsetWidth) + "\">"); | ||
}, ''); | ||
this.fixedHeaderTable.style.width = table.offsetWidth + 'px'; | ||
// 同步表头的高度 | ||
this.fixedTheadRow.style.height = theadRow.offsetHeight + 'px'; | ||
}; | ||
/** 重载 setData 方法,在渲染完表格后同步表头的内容。 */ | ||
anonymous.prototype.setData = function setData (data) { | ||
var this$1 = this; | ||
hooks.forEach(function (fn) { fn(this) }, this) | ||
this._init() | ||
} | ||
Base.prototype.setData.call(this, data); | ||
this.fixedTheadRow.innerHTML = this.ui.theadRow.innerHTML; | ||
// 需要等到 fixedTable 中的 syncFixedWidth 更新完之后再同步宽度, | ||
// 不然会出现 header 宽度不一致的问题 | ||
raf(function () { | ||
this$1.syncFixedHeader(); | ||
}); | ||
}; | ||
anonymous.prototype.destroy = function destroy () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
/** | ||
* 保存插件 | ||
* @param {Function} plugin | ||
*/ | ||
DataGrid.use = function (plugin) { | ||
if (true) { | ||
if (typeof plugin !== 'function') { | ||
throw new TypeError('.use(plugin) 参数类型错误: plugin 必需是一个函数。') | ||
} | ||
if (plugin._installed) return | ||
plugin._installed = true | ||
} | ||
plugin(DataGrid) | ||
} | ||
this.unbindEvents.forEach(function (unbind) { return unbind(); }); | ||
Base.prototype.destroy.apply(this, args); | ||
}; | ||
/** | ||
* 每次创建新的实例时都会触发这个函数 | ||
* @param {Function} fn | ||
* @return {function()} | ||
*/ | ||
DataGrid.hook = function (fn) { | ||
hooks.push(fn) | ||
return function () { | ||
var i = hooks.indexOf(fn) | ||
if (i >= 0) hooks.splice(i, 1) | ||
} | ||
} | ||
return anonymous; | ||
}(Base)); | ||
}; | ||
var dp = DataGrid.prototype = Object.create(Event.prototype) | ||
dp.constructor = DataGrid | ||
var prototype = Element.prototype; | ||
// https://caniuse.com/#feat=matchesselector | ||
var matches = prototype.matches || | ||
prototype.webkitMatchesSelector || | ||
prototype.msMatchesSelector; | ||
// https://caniuse.com/#feat=element-closest | ||
var closest = prototype.closest || | ||
function (s) { | ||
var el = this; | ||
do { | ||
if (matches.call(el, s)) | ||
{ return el; } | ||
el = el.parentElement; | ||
} while (el); | ||
return null; | ||
}; | ||
dp._init = function () { | ||
var _unbindEvents = this._unbindEvents = [] | ||
this.emit('beforeInit') | ||
var el = this.el | ||
el.classList.add(CssClassNamespace) | ||
el.innerHTML = containerTemplate | ||
__$styleInject(".fixed-grid{position:absolute;top:0;background:#fff}.fixed-grid .scroll-container{overflow:hidden}.fixed-grid-left{left:0}.fixed-grid-right{right:0}",undefined); | ||
var ui = { | ||
$gridWrapper: '.grid-wrapper', | ||
$columnsWrapper: '.grid-columns-wrapper', | ||
$columns: '.grid-columns', | ||
$columnsColGroup: '.grid-columns colgroup', | ||
$columnsThead: '.grid-columns thead', | ||
$bodyWrapper: '.grid-body-wrapper', | ||
$body: '.grid-body', | ||
$bodyColGroup: '.grid-body colgroup', | ||
$bodyTbody: '.grid-body tbody', | ||
$noData: '.grid-no-data' | ||
} | ||
var ref$1 = Array.prototype; | ||
var some = ref$1.some; | ||
var forEach = ref$1.forEach; | ||
var indexOf = ref$1.indexOf; | ||
var fixedTable = function (Base) { | ||
return (function (Base) { | ||
function anonymous() { | ||
var this$1 = this; | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
for (var key in ui) { | ||
ui[key] = el.querySelector(ui[key]) | ||
} | ||
Base.apply(this, args); | ||
this.fixedTableEvents = []; | ||
var ref = this.ui; | ||
var scrollContainer = ref.scrollContainer; | ||
if (!this.parent) { | ||
this.fixedTableEvents.push( | ||
// 同步表格的滚动条位置 | ||
addEvent(scrollContainer, 'scroll', rafThrottle(function () { | ||
var ref = this$1; | ||
var fixedTables = ref.fixedTables; | ||
if (!fixedTables) | ||
{ return; } | ||
for (var place in fixedTables) { | ||
fixedTables[place].ui.table.style[ | ||
// @ts-ignore | ||
getCSSProperty('transform')] = "translate3d(0,-" + (scrollContainer.scrollTop) + "px,0)"; | ||
} | ||
})), | ||
// 同步表格的 hover 状态 | ||
addEvent(this.el, 'mouseover', function (e) { | ||
var tr = closest.call(e.target, '.datagrid tbody tr'); | ||
if (!tr) | ||
{ return; } | ||
var trs = tr.parentElement.children; | ||
var ref = this$1; | ||
var lastHoverIndex = ref.lastHoverIndex; | ||
var index = indexOf.call(trs, tr); | ||
if (lastHoverIndex === index) | ||
{ return; } | ||
this$1.lastHoverIndex = index; | ||
var setHover = function (grid) { | ||
var trs = grid.ui.tbody.children; | ||
var lastHoverTr = trs[lastHoverIndex]; | ||
if (lastHoverTr) { | ||
lastHoverTr.classList.remove('hover-row'); | ||
} | ||
trs[index].classList.add('hover-row'); | ||
}; | ||
setHover(this$1); | ||
var ref$1 = this$1; | ||
var children = ref$1.children; | ||
if (children) { | ||
children.forEach(setHover); | ||
} | ||
})); | ||
} | ||
} | ||
ui.$gridWrapper.style.height = this.options.height + 'px' | ||
if ( Base ) anonymous.__proto__ = Base; | ||
anonymous.prototype = Object.create( Base && Base.prototype ); | ||
anonymous.prototype.constructor = anonymous; | ||
/** | ||
* 创建或更新固定在左侧或右侧的表格。 | ||
* @param count 固定表格的列数。 | ||
* @param place 固定表格的位置,默认为左侧。 | ||
*/ | ||
anonymous.prototype.setFixed = function setFixed (count, place) { | ||
if ( place === void 0 ) place = 'left'; | ||
var that = this | ||
_unbindEvents.push( | ||
// body 横向滚动时, 也要调整 columns 的左边距 | ||
addEvent(ui.$bodyWrapper, 'scroll', function () { | ||
ui.$columns.style.left = '-' + ui.$bodyWrapper.scrollLeft + 'px' | ||
}), | ||
// 鼠标移入或移出的时候,给 tr 加上 hover 状态。 | ||
// 之所以不用 css 实现,是因为 fixedGrid 需要能用 js 设置 tr 的 hover 状态 | ||
addEvent(ui.$bodyWrapper, 'mouseover', function (e) { | ||
var tr = findParent('tr', e.target) | ||
if (!tr) return | ||
var trIndex = tr.getAttribute('data-index') | ||
if (trIndex) { | ||
that.trHover(true, Number(trIndex)) | ||
} | ||
}), | ||
addEvent(ui.$bodyWrapper, 'mouseout', function (e) { | ||
var tr = findParent('tr', e.target) | ||
if (!tr) return | ||
var trIndex = tr.getAttribute('data-index') | ||
if (trIndex) { | ||
that.trHover(false, Number(trIndex)) | ||
} | ||
}), | ||
// 点击 cell 的时候给出一个事件 | ||
addEvent(ui.$bodyWrapper, 'click', function (e) { | ||
var td = findParent('td', e.target) | ||
if (!td) return | ||
var tr = findParent('tr', td) | ||
if (!tr) return | ||
var tdIndex = td.getAttribute('data-index') | ||
var trIndex = tr.getAttribute('data-index') | ||
var renderData = that.renderData | ||
that.emit('cellClick', renderData.columnsDef[tdIndex], that.empty ? null : renderData.rows[trIndex]) | ||
}), | ||
// 双击 cell 的时候给出一个事件 | ||
addEvent(ui.$bodyWrapper, 'dblclick', function (e) { | ||
var td = findParent('td', e.target) | ||
if (!td) return | ||
var tr = findParent('tr', td) | ||
if (!tr) return | ||
var tdIndex = td.getAttribute('data-index') | ||
var trIndex = tr.getAttribute('data-index') | ||
var renderData = that.renderData | ||
that.emit('cellDoubleClick', renderData.columnsDef[tdIndex], that.empty ? null : renderData.rows[trIndex]) | ||
}) | ||
) | ||
var ref = this; | ||
var fixedTables = ref.fixedTables; | ||
var fixedTable = fixedTables && fixedTables[place]; | ||
if (!count) { | ||
if (fixedTable) { | ||
fixedTable.el.style.display = 'none'; | ||
} | ||
return; | ||
} | ||
if (!fixedTable) { | ||
fixedTable = this.createFixedGrid(place); | ||
} | ||
var ref$1 = this; | ||
var curData = ref$1.curData; | ||
fixedTable.fixedColumns = count; | ||
fixedTable.setData({ | ||
columns: place === 'left' | ||
? curData.columns.slice(0, count) | ||
: curData.columns.slice(-count), | ||
rows: curData.rows | ||
}); | ||
fixedTable.el.style.display = ''; | ||
this.syncFixedWidth(place); | ||
}; | ||
/** | ||
* 同步一个固定表格的宽度、高度等状态。 | ||
* @param place 要同步宽度的表格的位置。 | ||
*/ | ||
anonymous.prototype.syncFixedWidth = function syncFixedWidth (place) { | ||
var ref = this; | ||
var fixedTables = ref.fixedTables; | ||
var fixedTable = fixedTables && fixedTables[place]; | ||
if (!fixedTable) | ||
{ return; } | ||
var fixed = fixedTable.fixedColumns; | ||
// 同步 table 和 th 的宽度 | ||
var colHtml = ''; | ||
// let width = 0 | ||
var ths = this.ui.theadRow.children; | ||
var thsLength = ths.length - 1; | ||
var getTh = place === 'left' | ||
? function (index) { return ths[index]; } | ||
: function (index) { return ths[thsLength - index]; }; | ||
some.call(ths, function (th, index) { | ||
if (index === fixed) | ||
{ return true; } | ||
var ref = getTh(index); | ||
var offsetWidth = ref.offsetWidth; | ||
colHtml += "<col width=\"" + offsetWidth + "\">"; | ||
// width += offsetWidth | ||
}); | ||
// 在使用默认主题(给 th 加了右 border)的情况下, | ||
// 给容器固定这个宽度可以让固定表格两侧的 border 不显示出来 | ||
// fixedTable.el.style.width = `${width}px` | ||
fixedTable.ui.colgroup.innerHTML = colHtml; | ||
// 同步表头的高度 | ||
fixedTable.ui.theadRow.style.height = this.ui.theadRow.offsetHeight + 'px'; | ||
// 同步 tr 的高度 | ||
var trs = fixedTable.ui.tbody.children; | ||
forEach.call(this.ui.tbody.children, function (tr, index) { | ||
trs[index].style.height = | ||
tr.offsetHeight + 'px'; | ||
}); | ||
}; | ||
/** | ||
* 创建固定在两侧的表格实例的方法。 | ||
* @param place 表格的位置 | ||
*/ | ||
anonymous.prototype.createFixedGrid = function createFixedGrid (place) { | ||
var innerTable = new this.constructor(Object.assign({ | ||
parent: this | ||
}, this.options)); | ||
innerTable.fixedPlace = place; | ||
(this.children || (this.children = [])).push(innerTable); | ||
(this.fixedTables || (this.fixedTables = {}))[place] = innerTable; | ||
innerTable.el.classList.add('fixed-grid', 'fixed-grid-' + place); | ||
var ui = innerTable.ui; | ||
var colgroup = (ui.colgroup = document.createElement('colgroup')); | ||
ui.table.appendChild(colgroup); | ||
this.el.appendChild(innerTable.el); | ||
return innerTable; | ||
}; | ||
this.ui = ui | ||
return anonymous; | ||
}(Base)); | ||
}; | ||
if (this.options.fit) { | ||
_unbindEvents.push( | ||
addEvent(window, 'resize', debounce(function () { | ||
that.setWidth() | ||
})) | ||
) | ||
} | ||
__$styleInject(".datagrid th.sortable{cursor:pointer}.datagrid .asc,.datagrid .desc{display:none}.datagrid .sort-by-1 .asc,.datagrid .sort-by-2 .desc{display:inline-block}",undefined); | ||
this.emit('afterInit') | ||
} | ||
/* tslint:enable:no-unused-variable */ | ||
// const DESC = -1, // 降序 | ||
// ASC = 1, // 升序 | ||
// NONE = 0 // 不排序 | ||
var orderLength = 3; | ||
var ref$2 = Array.prototype; | ||
var indexOf$1 = ref$2.indexOf; | ||
function defaultSortBlock() { | ||
var fd = document.createDocumentFragment(); | ||
[ | ||
{ | ||
className: 'asc', | ||
innerHTML: '↑' | ||
}, | ||
{ | ||
className: 'desc', | ||
innerHTML: '↓' | ||
} | ||
].forEach(function (element) { | ||
var span = document.createElement('span'); | ||
Object.assign(span, element); | ||
fd.appendChild(span); | ||
}); | ||
return fd; | ||
} | ||
var sort = function (Base) { | ||
return (function (Base) { | ||
function anonymous() { | ||
var this$1 = this; | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
/** | ||
* 处理 tr 元素的 hover 状态 | ||
* @param {Boolean} inOrOut - 此元素需要添加(true)还是移除(false) hover 状态 | ||
* @param {Number} index - 元素的 index | ||
* @param {Boolean} emit - 设为 false 则不触发相关事件 | ||
*/ | ||
dp.trHover = function (inOrOut, index, emit) { | ||
var tbody = this.ui.$bodyTbody | ||
var hoverToTR = tbody.querySelector('tr[data-index="' + index + '"]') | ||
hoverToTR.classList[inOrOut ? 'add' : 'remove']('hover') | ||
if (emit !== false) this.emit(inOrOut ? 'trHoverTo' : 'clearHover', index, hoverToTR, this.rows && this.rows[index]) | ||
} | ||
Base.apply(this, args); | ||
this.sortOrderIndex = 0; | ||
var sortBlock = this.options.sortBlock || defaultSortBlock; | ||
var appendSortBlock = typeof sortBlock === 'string' | ||
? function (th) { | ||
th.innerHTML += sortBlock; | ||
} | ||
: function (th) { | ||
th.appendChild(sortBlock()); | ||
}; | ||
this.on('after th render', function (th, column, index) { | ||
if (index === this$1.sortColumnIndex && this$1.sortOrderIndex) { | ||
th.classList.add('sort-by-' + this$1.sortOrderIndex); | ||
} | ||
// TODO: 后期增加只针对某些 column 开启排序的功能 | ||
th.classList.add('sortable'); | ||
appendSortBlock(th); | ||
}); | ||
if (!this.parent) { | ||
addEvent(this.el, 'click', function (e) { | ||
var th = closest.call(e.target, '.datagrid th'); | ||
if (!th) | ||
{ return; } | ||
var ths = th.parentElement.children; | ||
var thIndex = indexOf$1.call(ths, th); | ||
var newSortColumnIndex; | ||
var isRightFixed = closest.call(th, '.fixed-grid-right'); | ||
if (isRightFixed) { | ||
newSortColumnIndex = | ||
this$1.curData.columns.length - | ||
(this$1.fixedTables.right.fixedColumns - thIndex); | ||
} | ||
else { | ||
newSortColumnIndex = thIndex; | ||
} | ||
var newOrderIndex; | ||
var oldOrderIndex = this$1.sortOrderIndex; | ||
var oldSortColumnIndex = this$1.sortColumnIndex; | ||
if (oldSortColumnIndex !== newSortColumnIndex) { | ||
this$1.sortColumnIndex = newSortColumnIndex; | ||
newOrderIndex = 1; | ||
} | ||
else { | ||
newOrderIndex = this$1.sortOrderIndex + 1; | ||
if (newOrderIndex >= orderLength) { | ||
newOrderIndex -= orderLength; | ||
} | ||
} | ||
this$1.sortOrderIndex = newOrderIndex; | ||
var setSort = function (grid) { | ||
var columnIndex2trIndex = function (columnIndex) { | ||
return grid.fixedPlace === 'right' | ||
? grid.fixedColumns - | ||
(this$1.curData.columns.length - columnIndex) | ||
: columnIndex; | ||
}; | ||
var ths = (grid.ui.fixedTheadRow || grid.ui.theadRow).children; | ||
if (oldOrderIndex) { | ||
var oldTh = ths[columnIndex2trIndex(oldSortColumnIndex)]; | ||
if (oldTh) { | ||
oldTh.classList.remove('sort-by-' + oldOrderIndex); | ||
} | ||
} | ||
if (newOrderIndex) { | ||
var newTh = ths[columnIndex2trIndex(newSortColumnIndex)]; | ||
console.log(grid.fixedPlace === 'right' | ||
? grid.fixedColumns - | ||
(this$1.curData.columns.length - newSortColumnIndex) | ||
: newSortColumnIndex); | ||
if (newTh) { | ||
newTh.classList.add('sort-by-' + newOrderIndex); | ||
} | ||
} | ||
}; | ||
setSort(this$1); | ||
var ref = this$1; | ||
var children = ref.children; | ||
if (children) { | ||
children.forEach(setSort); | ||
} | ||
this$1.emit('sort', thIndex, newOrderIndex); | ||
}); | ||
} | ||
} | ||
/** | ||
* 给表格填充数据 | ||
* @param data | ||
* @param {String[]|Object[]} data.columns - 表格的字段定义 | ||
* @param {Object[]} data.rows - 数据 | ||
* @param {Number[]} data.width - 每个字段对应的宽度 | ||
*/ | ||
dp.setData = function (data) { | ||
this.renderData = {} | ||
this.emit('beforeSetData', data) | ||
this.empty = !(data.columns && data.columns.length) || (!(data.rows && data.rows.length)) | ||
if (this.empty) { | ||
var ui = this.ui | ||
ui.$body.classList.add('hidden') | ||
ui.$noData.classList.remove('hidden') | ||
} else { | ||
this.setColumns(data.columns) | ||
this.setBody(data.rows) | ||
this.setWidth(data.width) | ||
} | ||
this.emit('afterSetData', data) | ||
} | ||
if ( Base ) anonymous.__proto__ = Base; | ||
anonymous.prototype = Object.create( Base && Base.prototype ); | ||
anonymous.prototype.constructor = anonymous; | ||
/** | ||
* 根据用户给的宽度数组计算出实际需要用到的最小宽度数组, | ||
* 因为用户可能不传宽度数组,或者宽度数组的长度比字段数组长或短, | ||
* 所以要处理一遍 | ||
* @param {Array} [widthArr] | ||
* @return {Array} | ||
*/ | ||
dp.normalizeWidth = function (widthArr) { | ||
var renderData = this.renderData | ||
var columnsDef = renderData.columnsDef | ||
if (!Array.isArray(widthArr)) widthArr = [] | ||
var result = [] | ||
for (var i = 0; i < columnsDef.length; i++) { | ||
result[i] = widthArr[i] || Math.max((columnsDef[i].name || '').length * 15, DefaultWidth) | ||
} | ||
return result | ||
} | ||
return anonymous; | ||
}(Base)); | ||
}; | ||
/** | ||
* 设置宽度。 | ||
* 默认情况下,用户设置的宽度会成为最终字段的宽度, | ||
* 但如果 fit 设置为 true,则将用户传进来的宽度视为"最小宽度", | ||
* 如果这些最小宽度加起来大于 wrapper 的宽度,则直接使用最小宽度作为 td 的宽度; | ||
* 如果加起来小于 wrapper 的宽度,则用 wrapper 宽度减去最小宽度的差值,除以字段的个数得到平均值,再给每个最小宽度加上这个平均值作为字段的真正宽度 | ||
* @param {Number[]} [width] | ||
*/ | ||
dp.setWidth = function (width) { | ||
if (this.empty) return | ||
var obj = { width: width } | ||
this.emit('beforeSetWidth', obj) | ||
var renderData = this.renderData | ||
var ref$3 = Array.prototype; | ||
var indexOf$2 = ref$3.indexOf; | ||
var selection = function (Base) { | ||
return (function (Base) { | ||
function anonymous() { | ||
var this$1 = this; | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
var customWidth = obj.width | ||
if (customWidth || !renderData.columnsMinWidth) { | ||
renderData.columnsMinWidth = this.normalizeWidth(customWidth) | ||
} | ||
Base.apply(this, args); | ||
if (!this.parent) { | ||
addEvent(this.el, 'click', function (e) { | ||
var tr = closest.call(e.target, '.datagrid tbody tr'); | ||
if (!tr) | ||
{ return; } | ||
var trs = tr.parentElement.children; | ||
var trIndex = indexOf$2.call(trs, tr); | ||
var oldSelectionIndex = this$1.selectionIndex; | ||
if (oldSelectionIndex !== trIndex) { | ||
this$1.selectionIndex = trIndex; | ||
this$1.emit('select', trIndex); | ||
var updateSelected = function (grid) { | ||
var ref = grid.ui.tbody; | ||
var children = ref.children; | ||
var lastSelectedRow = children[oldSelectionIndex]; | ||
if (lastSelectedRow) { | ||
lastSelectedRow.classList.remove('selected-row'); | ||
} | ||
children[trIndex].classList.add('selected-row'); | ||
}; | ||
updateSelected(this$1); | ||
var ref = this$1; | ||
var children = ref.children; | ||
if (children) { | ||
children.forEach(updateSelected); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
var columnsMinWidth = renderData.columnsMinWidth | ||
var columnsWidth | ||
if ( Base ) anonymous.__proto__ = Base; | ||
anonymous.prototype = Object.create( Base && Base.prototype ); | ||
anonymous.prototype.constructor = anonymous; | ||
if (this.options.fit) { | ||
var sum = columnsMinWidth.reduce(function (w1, w2) { | ||
return w1 + w2 | ||
}) | ||
var bodyWrapperWidth = this.ui.$bodyWrapper.clientWidth | ||
if (sum >= bodyWrapperWidth) { | ||
columnsWidth = columnsMinWidth | ||
} else { | ||
var diff = (bodyWrapperWidth - sum) / renderData.columnsDef.length | ||
columnsWidth = columnsMinWidth.map(function (w) { | ||
return Math.round(w + diff) | ||
}) | ||
} | ||
} else { | ||
columnsWidth = columnsMinWidth | ||
} | ||
renderData.columnsWidth = columnsWidth | ||
var cols = this._colGroupsHTML(columnsWidth) | ||
this._renderCols(cols) | ||
this._resize(columnsWidth) | ||
} | ||
return anonymous; | ||
}(Base)); | ||
}; | ||
/** | ||
* 计算出表格的 col 元素的 HTML | ||
* @param {Number[]} columnsWidth - 定义字段宽度的数组 | ||
* @private | ||
* @return {String[]} | ||
*/ | ||
dp._colGroupsHTML = function (columnsWidth) { | ||
return columnsWidth ? columnsWidth.map(function (width) { return '<col style="width:' + width + 'px">' }) : [] | ||
} | ||
/* tslint:enable:no-unused-variable */ | ||
/* tslint:disable:no-duplicate-imports */ | ||
/* tslint:enable:no-duplicate-imports */ | ||
// 默认返回一个功能丰富的表格类。 | ||
// 这里的繁琐写法是为了让 TypeScript 能正确解析类型。 | ||
// | ||
// 注意:由于同时使用了 `export` 和 `export default`, | ||
// CommonJS 和浏览器端要使用 `default` 属性读取到这个输出。 | ||
// | ||
// CommonJS: `const DataGrid = require('datagrid').default` | ||
// 浏览器:`const Grid = DataGrid.default` | ||
var index = selection(sort(fixedHeader(fixedTable(BaseGrid)))); | ||
/** | ||
* 填充 colsHTML | ||
* @param {String[]} colsHTML | ||
* @private | ||
*/ | ||
dp._renderCols = function (colsHTML) { | ||
var ui = this.ui | ||
ui.$columnsColGroup.innerHTML = ui.$bodyColGroup.innerHTML = colsHTML.join('') | ||
} | ||
exports['default'] = index; | ||
exports.BaseGrid = BaseGrid; | ||
exports.fixedHeader = fixedHeader; | ||
exports.fixedTable = fixedTable; | ||
/** | ||
* 调整各种尺寸 | ||
* @param {Number[]} columnsWidth | ||
* @private | ||
*/ | ||
dp._resize = function (columnsWidth) { | ||
var ui = this.ui | ||
var $columns = ui.$columns | ||
var $noData = ui.$noData | ||
var $body = ui.$body | ||
var _totalWidth = columnsWidth.reduce(function (prev, width) { return prev + width }) | ||
$columns.style.width = $body.style.width = _totalWidth + 'px' | ||
if (this.empty) { | ||
$noData.classList.remove('hidden') | ||
} else { | ||
$noData.classList.add('hidden') | ||
} | ||
} | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
/** | ||
* 渲染表头的方法 | ||
* @param {String[]|Object[]} columns | ||
* @private | ||
*/ | ||
dp.setColumns = function (columns) { | ||
var columnsDef = this.renderData.columnsDef = this._normalize(columns) | ||
var columnsHTML = this._columnsHTML(columnsDef) | ||
this.emit('beforeRenderColumns', columnsHTML) | ||
this._renderColumns(columnsHTML) | ||
} | ||
/** | ||
* 调整字段定义, 并根据字段定义计算出每个字段的宽度数组 | ||
* @param columns | ||
* @private | ||
*/ | ||
dp._normalize = function (columns) { | ||
return columns.map(function (columnDef) { | ||
var _def = typeof columnDef === 'string' | ||
? { name: columnDef } | ||
: columnDef | ||
if (!_def.key) _def.key = _def.name | ||
return _def | ||
}) | ||
} | ||
/** | ||
* 计算出渲染表头字段的 HTML | ||
* @private | ||
*/ | ||
dp._columnsHTML = function (columnsDef) { | ||
var customRenderer = this.options.thRenderer | ||
return columnsDef.map(function (columnDef, index) { | ||
var content | ||
if (columnDef.thRenderer) { | ||
content = columnDef.thRenderer(columnDef) | ||
} | ||
if (content == null) { | ||
if (customRenderer) { | ||
content = customRenderer(columnDef) | ||
} | ||
if (content == null) { | ||
content = defaultThRenderer(columnDef) | ||
} | ||
} | ||
return '<th data-index="' + index + '">' + content + '</th>' | ||
}) | ||
} | ||
/** | ||
* 渲染表头 | ||
* @param {String[]} columnsHTML | ||
* @private | ||
*/ | ||
dp._renderColumns = function (columnsHTML) { | ||
this.ui.$columnsThead.innerHTML = columnsHTML.join('') | ||
} | ||
/** | ||
* 渲染表格的方法 | ||
* @param {Object[]} rows | ||
*/ | ||
dp.setBody = function (rows) { | ||
var renderData = this.renderData | ||
this.empty = !rows || !rows.length | ||
renderData.rows = rows | ||
this._renderBody(renderData.trsArr = this._bodyHTML(renderData.columnsDef, rows)) | ||
} | ||
/** | ||
* 计算出渲染 body 需要的数据 | ||
* @private | ||
*/ | ||
dp._bodyHTML = function (columnsDef, rows) { | ||
var customRenderer = this.options.tdRenderer | ||
return this.empty ? [] : rows.map(function (row, rowIndex) { | ||
var rowHTML = '<tr data-index="' + rowIndex + '">' | ||
columnsDef.forEach(function (columnDef, columnIndex) { | ||
var content | ||
if (columnDef.tdRenderer) { | ||
content = columnDef.tdRenderer(columnDef, row) | ||
} | ||
if (content == null) { | ||
if (customRenderer) { | ||
content = customRenderer(columnDef, row) | ||
} | ||
if (content == null) { | ||
content = defaultTdRenderer(columnDef, row) | ||
} | ||
} | ||
rowHTML += '<td data-index="' + columnIndex + '">' + content + '</td>' | ||
}) | ||
rowHTML += '</tr>' | ||
return rowHTML | ||
}) | ||
} | ||
/** | ||
* 渲染数据 | ||
* @param {String[]} trsArr | ||
* @private | ||
*/ | ||
dp._renderBody = function (trsArr) { | ||
var ui = this.ui | ||
ui.$bodyTbody.innerHTML = trsArr.join('') | ||
ui.$body.classList.remove('hidden') | ||
ui.$noData.classList.add('hidden') | ||
} | ||
/** | ||
* 销毁实例 | ||
*/ | ||
dp.destroy = function () { | ||
this.emit('beforeDestroy') | ||
this._unbindEvents.forEach(function (unbind) { unbind() }) | ||
// 还原原本的 dom 节点 | ||
var el = this.el | ||
try { | ||
el.parentElement.replaceChild(this.origin, el) | ||
} catch (e) {} | ||
this.emit('afterDestroy') | ||
} | ||
module.exports = DataGrid | ||
/***/ }, | ||
/* 2 */ | ||
/***/ function(module, exports) { | ||
// removed by extract-text-webpack-plugin | ||
/***/ }, | ||
/* 3 */, | ||
/* 4 */, | ||
/* 5 */, | ||
/* 6 */ | ||
/***/ function(module, exports) { | ||
module.exports = "<div class=\"grid-wrapper\">\n <div class=\"grid-columns-wrapper\">\n <table class=\"grid-columns\">\n <colgroup></colgroup>\n <thead></thead>\n </table>\n </div>\n <div class=\"grid-body-wrapper\">\n <table class=\"grid-body\">\n <colgroup></colgroup>\n <tbody></tbody>\n </table>\n </div>\n</div>\n<div class=\"grid-no-data hidden\">\n <div class=\"no-data-content\">\n 暂无数据\n </div>\n</div>\n"; | ||
/***/ }, | ||
/* 7 */ | ||
/***/ function(module, exports) { | ||
var slice = Array.prototype.slice | ||
function MyEvent () { | ||
this._callbacks = {} | ||
} | ||
var p = MyEvent.prototype | ||
/** | ||
* 注册事件监听函数 | ||
* @param {string} eventName | ||
* @param {function()} handlerFunc | ||
* @return {function()} - 调用此函数可以取消掉监听 | ||
*/ | ||
p.on = function (eventName, handlerFunc) { | ||
var callbacks = this._callbacks | ||
var eventArr = (callbacks[eventName] || (callbacks[eventName] = [])) | ||
eventArr.push(handlerFunc) | ||
return function () { | ||
var i = eventArr.indexOf(handlerFunc) | ||
if (i >= 0) eventArr.splice(i, 1) | ||
} | ||
} | ||
/** | ||
* 注册事件监听函数, 但只监听一次 | ||
* @param {string} eventName | ||
* @param {function()} handlerFunc | ||
* @return {function()} | ||
*/ | ||
p.once = function (eventName, handlerFunc) { | ||
var unwatch = this.on(eventName, function () { | ||
handlerFunc.apply(null, arguments) | ||
// 等 emit 中的 forEach 执行完后再改变数组 | ||
window.setTimeout(unwatch, 0) | ||
}) | ||
return unwatch | ||
} | ||
/** | ||
* 发布事件 | ||
* @param {string} eventName | ||
*/ | ||
p.emit = function (eventName/* , ...args */) { | ||
var eventArr = this._callbacks[eventName] | ||
if (!eventArr || !eventArr.length) return | ||
var args = slice.call(arguments, 1) | ||
eventArr.forEach(function (func) { | ||
func.apply(null, args) | ||
}) | ||
} | ||
module.exports = MyEvent | ||
/***/ }, | ||
/* 8 */ | ||
/***/ function(module, exports) { | ||
/** | ||
* 给元素注册事件, 并返回一个函数用于解绑事件 | ||
* @param {EventTarget} element | ||
* @param {String} eventName | ||
* @param {Function} handler | ||
* @param {Boolean} [useCapture] | ||
* @return {function()} | ||
*/ | ||
module.exports = function (element, eventName, handler, useCapture) { | ||
element.addEventListener(eventName, handler, useCapture) | ||
return function () { | ||
element.removeEventListener(eventName, handler, useCapture) | ||
} | ||
} | ||
/***/ }, | ||
/* 9 */ | ||
/***/ function(module, exports) { | ||
var has = Object.prototype.hasOwnProperty | ||
module.exports = function (target) { | ||
for (var i = 1; i < arguments.length; i += 1) { | ||
var d = arguments[i] | ||
if (!d || typeof d !== 'object') continue | ||
for (var key in d) { | ||
if (has.call(d, key)) { | ||
target[key] = d[key] | ||
} | ||
} | ||
} | ||
return target | ||
} | ||
/***/ }, | ||
/* 10 */ | ||
/***/ function(module, exports) { | ||
/** | ||
* 寻找一个元素指定名称的父元素 | ||
* @param {String} tagName - 要寻找的元素名 | ||
* @param {HTMLElement} node - 从哪个元素开始寻找 | ||
* @param {HTMLElement} [stop] - 碰到这个元素时停止查找 | ||
* @return {null|HTMLElement} | ||
*/ | ||
module.exports = function (tagName, node, stop) { | ||
if (!stop) stop = document.body | ||
var tag = tagName.toUpperCase() | ||
var parent = node | ||
var tr = null | ||
do { | ||
if (parent.tagName === tag) { | ||
tr = parent | ||
break | ||
} | ||
} while (parent !== stop && (parent = parent.parentElement)) | ||
return tr | ||
} | ||
/***/ }, | ||
/* 11 */ | ||
/***/ function(module, exports) { | ||
/** | ||
* 返回一个延迟执行的函数 | ||
* @param {Function} fn | ||
* @param {Number} [timeout] | ||
* @return {Function} | ||
*/ | ||
module.exports = function (fn, timeout) { | ||
var timeId | ||
timeout = typeof timeout === 'number' ? timeout : 250 | ||
return function () { | ||
if (typeof timeId === 'number') window.clearTimeout(timeId) | ||
var args = arguments | ||
timeId = window.setTimeout(function () { | ||
fn.apply(null, args) | ||
}, timeout) | ||
} | ||
} | ||
/***/ }, | ||
/* 12 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
// todo selection 插件的全选功能目前无法与 fixedColumns 插件共同使用 | ||
__webpack_require__(13) | ||
var findParent = __webpack_require__(10) | ||
var addEvent = __webpack_require__(8) | ||
var SelectedClassName = 'selected' | ||
module.exports = function (DataGrid) { | ||
DataGrid.prototype.selectRow = function (index, fire) { | ||
var $body = this.ui.$body | ||
var tr = $body.querySelector('tr[data-index="' + index + '"]') | ||
if (!tr) return | ||
// 如果是多选,则判断当前点击的行是否已被选中, | ||
// 如果已被选中,则删除选中状态, | ||
// 否则添加选中状态 | ||
var i = this._selectRowsIndex.indexOf(index) | ||
// 多选状态下,如果此行已被选中,则清除此行的选中状态; | ||
// 如果没被选中,则添加选中状态 | ||
if (this._isMultipleSelect) { | ||
if (i >= 0) { | ||
this._selectRowsIndex.splice(i, 1) | ||
} else { | ||
this._selectRowsIndex.push(index) | ||
} | ||
} else { | ||
// 单选状态下,如果已被选中则直接返回,不做任何操作; | ||
// 否则删除上次选中状态并给当前行添加选中状态 | ||
if (i >= 0) return | ||
var selectedTR = $body.querySelector('tr.' + SelectedClassName) | ||
if (selectedTR) selectedTR.classList.remove(SelectedClassName) | ||
tr.classList.add('selected') | ||
this._selectRowsIndex = [index] | ||
} | ||
if (fire !== false) this.emit('selectedChanged', this._isMultipleSelect ? this._selectRowsIndex : index) | ||
} | ||
DataGrid.prototype.selectAll = function (allOrNone, fire) { | ||
if (!this._isMultipleSelect) return | ||
this._selectRowsIndex = [] | ||
var that = this | ||
Array.prototype.forEach.call(this.ui.$bodyWrapper.querySelectorAll('tr[data-index]'), function (tr) { | ||
if (allOrNone) { | ||
var index = Number(tr.getAttribute('data-index')) | ||
that._selectRowsIndex.push(index) | ||
} | ||
tr.querySelector('input[type=checkbox]').checked = allOrNone | ||
}) | ||
if (fire !== false) this.emit('selectedChanged', this._selectRowsIndex) | ||
} | ||
DataGrid.hook(function (datagrid) { | ||
var selectionType = datagrid.options.selection | ||
if (!selectionType) return | ||
var isMultiple = datagrid._isMultipleSelect = selectionType === 'multiple' | ||
var unbindEvents = [] | ||
unbindEvents.push(datagrid.on('beforeSetData', function () { | ||
datagrid._selectRowsIndex = [] | ||
})) | ||
if (isMultiple) { | ||
unbindEvents.push(datagrid.on('beforeSetData', function (data) { | ||
data.columns.unshift({ | ||
sortable: false, | ||
thRenderer: function () { | ||
return '<input type="checkbox" class="select-all">' | ||
}, | ||
tdRenderer: function () { | ||
return '<input type="checkbox">' | ||
} | ||
}) | ||
})) | ||
} | ||
datagrid.once('afterInit', function () { | ||
var $bodyWrapper = datagrid.ui.$bodyWrapper | ||
var $columnsWrapper = datagrid.ui.$columnsWrapper | ||
if (isMultiple) { | ||
// 点击开头的 checkbox 才触发事件 | ||
unbindEvents.push(addEvent($bodyWrapper, 'change', function (e) { | ||
if (e.target.tagName !== 'INPUT' || e.target.type !== 'checkbox') return | ||
$columnsWrapper.querySelector('input.select-all').checked = false | ||
var tr = findParent('tr', e.target, $bodyWrapper) | ||
if (!tr) return | ||
var trIndex = Number(tr.getAttribute('data-index')) | ||
if (!Number.isNaN(trIndex)) datagrid.selectRow(trIndex) | ||
// 等 datagrid.selectRow() 方法执行完成后,判断 _selectedRowsIndex 数组的长度是否等于 rows 的长度就知道是否是全选了 | ||
$columnsWrapper.querySelector('input[type=checkbox].select-all').checked = !datagrid.empty && datagrid._selectRowsIndex.length === datagrid.renderData.rows.length | ||
})) | ||
// 全选 checkbox | ||
unbindEvents.push(addEvent($columnsWrapper, 'change', function (e) { | ||
var input = e.target | ||
if (input.tagName !== 'INPUT' || input.type !== 'checkbox' || !input.classList.contains('select-all')) return | ||
datagrid.selectAll(input.checked) | ||
})) | ||
} else { | ||
// 点击数据行时, 给出事件提示 | ||
unbindEvents.push(addEvent($bodyWrapper, 'click', function (e) { | ||
var tr = findParent('tr', e.target, $bodyWrapper) | ||
if (!tr) return | ||
var trIndex = Number(tr.getAttribute('data-index')) | ||
if (!Number.isNaN(trIndex)) datagrid.selectRow(trIndex) | ||
})) | ||
} | ||
}) | ||
datagrid.once('beforeDestroy', function () { | ||
unbindEvents.forEach(function (unbind) { | ||
unbind() | ||
}) | ||
}) | ||
}) | ||
} | ||
/***/ }, | ||
/* 13 */ | ||
/***/ function(module, exports) { | ||
// removed by extract-text-webpack-plugin | ||
/***/ }, | ||
/* 14 */, | ||
/* 15 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
__webpack_require__(16) | ||
var pagerTemplate = __webpack_require__(18) | ||
var addEvent = __webpack_require__(8) | ||
module.exports = function (DataGrid) { | ||
DataGrid.hook(function (datagrid) { | ||
if (!datagrid.options.pagination) return | ||
var pagingTemplate = datagrid.options.pagingTemplate || pagerTemplate | ||
function jumpTo (pageNo) { | ||
if (Number.isNaN(pageNo) || pageNo < 1 || pageNo > pager.totalPage) { | ||
wrapper.querySelector('[data-page]').value = pager.cur | ||
return | ||
} | ||
wrapper.querySelector('[data-page]').value = pager.cur = pageNo | ||
datagrid.emit('switchPage', pageNo) | ||
} | ||
var pager = datagrid.pager = { | ||
cur: 1, // 当前页数 | ||
total: null, // 总共有多少条记录 | ||
size: null, // 每一页有多少条记录 | ||
start: null, // 当前页的数据是从第几条开始的 | ||
end: null, // 当前页的数据是在第几条结束的 | ||
totalPage: null // 一共有多少页 | ||
} | ||
var unbindEvents = [] | ||
var wrapper = document.createElement('div') | ||
wrapper.classList.add('grid-pager-wrapper') | ||
unbindEvents.push( | ||
addEvent(wrapper, 'click', function (e) { | ||
var jump = e.target.dataset.jump | ||
if (!jump) return | ||
var pageTo | ||
switch (jump) { | ||
case 'first': | ||
pageTo = 1 | ||
break | ||
case 'end': | ||
pageTo = pager.totalPage | ||
break | ||
case 'prev': | ||
pageTo = pager.cur - 1 | ||
break | ||
case 'next': | ||
pageTo = pager.cur + 1 | ||
break | ||
default: | ||
return | ||
} | ||
jumpTo(pageTo) | ||
}), | ||
addEvent(wrapper, 'keydown', function (e) { | ||
if (e.keyCode !== 13) return | ||
if (e.target.dataset.page === undefined) return | ||
jumpTo(Number(e.target.value)) | ||
}), | ||
datagrid.on('beforeSetData', function (data) { | ||
if (!data.rows || !data.rows.length) { | ||
wrapper.classList.add('hidden') | ||
return | ||
} | ||
var size = data.size || 0 | ||
var total = data.total || 0 | ||
var cur = pager.cur | ||
var dataLength = data.rows.length | ||
pager.total = total | ||
pager.size = size | ||
pager.start = (cur - 1) * size + 1 | ||
pager.end = pager.start + dataLength - 1 | ||
pager.total = total | ||
pager.totalPage = Math.ceil(total / size) || 0 | ||
wrapper.innerHTML = pagingTemplate.replace(/\{\{(\w+)\}\}/g, function (word, group) { | ||
return pager.hasOwnProperty(group) ? pager[group] : word | ||
}) | ||
wrapper.classList.remove('hidden') | ||
}) | ||
) | ||
datagrid.once('afterInit', function () { | ||
datagrid.ui.$gridWrapper.appendChild(wrapper) | ||
datagrid.ui.$pagerWrapper = wrapper | ||
}) | ||
datagrid.once('beforeDestroy', function () { | ||
unbindEvents.forEach(function (unbind) { unbind() }) | ||
}) | ||
}) | ||
} | ||
/***/ }, | ||
/* 16 */ | ||
/***/ function(module, exports) { | ||
// removed by extract-text-webpack-plugin | ||
/***/ }, | ||
/* 17 */, | ||
/* 18 */ | ||
/***/ function(module, exports) { | ||
module.exports = "<div class=\"grid-pager\">\n <div>显示第 {{start}} - {{end}} 条数据, 共 {{total}} 条数据</div>\n <div>\n <span data-jump=\"first\">首页</span>\n <span data-jump=\"prev\">上一页</span>\n <span>第 <input type=\"text\" data-page value=\"{{cur}}\"> 页, 共 {{totalPage}} 页</span>\n <span data-jump=\"next\">下一页</span>\n <span data-jump=\"end\">尾页</span>\n </div>\n</div>\n"; | ||
/***/ }, | ||
/* 19 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
__webpack_require__(20) | ||
var findParent = __webpack_require__(10) | ||
var addEvent = __webpack_require__(8) | ||
var DESC = -1 // 降序 | ||
var ASC = 1 // 升序 | ||
var NONE_ORDER = 0 // 不排序 | ||
var CLASS_ASC = 'order-by-asc' | ||
var CLASS_DESC = 'order-by-desc' | ||
module.exports = function (DataGrid) { | ||
DataGrid.prototype.sortBy = function (index, fire) { | ||
var columnDef = this.renderData.columnsDef[index] | ||
if (!columnDef || columnDef.sortable === false) return | ||
var sort = this.sort || (this.sort = {}) | ||
var $columnsWrapper = this.ui.$columnsWrapper | ||
var lastSortIndex = sort.index | ||
if (index !== lastSortIndex) { | ||
if (typeof lastSortIndex === 'number') { | ||
var lastTH = $columnsWrapper.querySelector('th[data-index="' + lastSortIndex + '"]') | ||
if (lastTH) lastTH.classList.remove(CLASS_ASC, CLASS_DESC) | ||
} | ||
sort.index = index | ||
sort.direction = NONE_ORDER | ||
} | ||
var th = $columnsWrapper.querySelector('th[data-index="' + index + '"]') | ||
th.classList.remove(CLASS_ASC, CLASS_DESC) | ||
switch (sort.direction) { | ||
case NONE_ORDER: | ||
sort.direction = ASC | ||
th.classList.add(CLASS_ASC) | ||
break | ||
case ASC: | ||
sort.direction = DESC | ||
th.classList.add(CLASS_DESC) | ||
break | ||
case DESC: | ||
sort.direction = NONE_ORDER | ||
break | ||
} | ||
if (fire !== false) this.emit('sort', columnDef, sort.direction, index, th) | ||
} | ||
DataGrid.hook(function (datagrid) { | ||
if (!datagrid.options.columnSorting) return | ||
var unbindEvents = [] | ||
unbindEvents.push( | ||
// 给每个字段内部注入小箭头 | ||
datagrid.on('beforeRenderColumns', function (columnsHTMLArr) { | ||
columnsHTMLArr.forEach(function (html, index) { | ||
columnsHTMLArr[index] = html.replace('</th>', '<span class="order-ico"></span></th>') | ||
}) | ||
}) | ||
) | ||
datagrid.once('afterInit', function () { | ||
// 监听字段的点击事件 | ||
var $columnsWrapper = datagrid.ui.$columnsWrapper | ||
unbindEvents.push( | ||
addEvent($columnsWrapper, 'click', function (e) { | ||
var th = findParent('th', e.target, $columnsWrapper) | ||
if (!th) return | ||
if (th.classList.contains('resizing')) return | ||
var index = Number(th.getAttribute('data-index')) | ||
if (!window.isNaN(index)) datagrid.sortBy(index) | ||
}), | ||
datagrid.on('afterSetData', function () { | ||
var lastSortColumnIndex = datagrid.sort && datagrid.sort.index | ||
if (typeof lastSortColumnIndex !== 'number' || lastSortColumnIndex < 0) return | ||
var th = datagrid.ui.$columnsWrapper.querySelector('th[data-index="' + lastSortColumnIndex + '"]') | ||
if (!th) return | ||
switch (datagrid.sort.direction) { | ||
case ASC: | ||
th.classList.add(CLASS_ASC) | ||
break | ||
case DESC: | ||
th.classList.add(CLASS_DESC) | ||
break | ||
} | ||
}) | ||
) | ||
}) | ||
datagrid.once('beforeDestroy', function () { | ||
unbindEvents.forEach(function (unbind) { unbind() }) | ||
}) | ||
}) | ||
} | ||
/***/ }, | ||
/* 20 */ | ||
/***/ function(module, exports) { | ||
// removed by extract-text-webpack-plugin | ||
/***/ }, | ||
/* 21 */, | ||
/* 22 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
__webpack_require__(23) | ||
var addEvent = __webpack_require__(8) | ||
var findParent = __webpack_require__(10) | ||
var MIN_WIDTH = 100 // 表格的最小宽度 | ||
var indexOf = Array.prototype.indexOf | ||
var IS_TOUCH = 'ontouchstart' in window | ||
var MOUSEDOWN = IS_TOUCH ? 'touchstart' : 'mousedown' | ||
var MOUSEMOVE = IS_TOUCH ? 'touchmove' : 'mousemove' | ||
var MOUSEUP = IS_TOUCH ? 'touchend' : 'mouseup' | ||
var getPageX = IS_TOUCH ? function (e) { | ||
return e.pageX || e.changedTouches[0].pageX | ||
} : function (e) { | ||
return e.pageX | ||
} | ||
module.exports = function (DataGrid) { | ||
DataGrid.hook(function (datagrid) { | ||
if (!datagrid.options.columnResize) return | ||
// 拖动时显示的虚线 | ||
var dragLine = document.createElement('div') | ||
dragLine.classList.add('dragging-line') | ||
var unbindEvents = [] | ||
// 注入虚线 | ||
datagrid.once('afterInit', function () { | ||
datagrid.ui.$draggingLine = dragLine | ||
datagrid.el.appendChild(dragLine) | ||
}) | ||
var dragging = false // 是否正在拖动中 | ||
var draggingTH // 被拖动的 th 元素 | ||
var draggingColumnIndex // 被拖动的元素是第几个字段 | ||
var startX // 拖动开始时的 pageX 值 | ||
var draggingLineInitLeft // 拖动开始时虚线的左编剧 | ||
var minLeft // 当往左边拖动时能拖动的最大距离 | ||
function showDragLine (th) { | ||
// 显示虚线 | ||
var ui = datagrid.ui | ||
var $columnsWrapper = ui.$columnsWrapper | ||
var $bodyWrapper = ui.$bodyWrapper | ||
dragLine.style.height = $columnsWrapper.offsetHeight + $bodyWrapper.offsetHeight + 'px' | ||
draggingLineInitLeft = th.offsetLeft + th.clientWidth - $bodyWrapper.scrollLeft | ||
dragLine.style.left = draggingLineInitLeft + 1 + 'px' | ||
document.documentElement.classList.add('data-grid-dragging') | ||
} | ||
// 在非触摸屏设备上,鼠标移上去的时候就显示拖拽虚线 | ||
if (!IS_TOUCH) { | ||
unbindEvents.push( | ||
addEvent(datagrid.el, 'mouseover', function (e) { | ||
if (!e.target.classList.contains('drag-lever')) return | ||
var th = findParent('th', e.target, datagrid.el) | ||
if (!th) return | ||
showDragLine(th) | ||
}), | ||
addEvent(datagrid.el, 'mouseout', function (e) { | ||
if (!e.target.classList.contains('drag-lever') || dragging) return | ||
document.documentElement.classList.remove('data-grid-dragging') | ||
}) | ||
) | ||
} | ||
unbindEvents.push( | ||
// 注入供用户拖拽的小方块 | ||
datagrid.on('beforeRenderColumns', function (columnsHTMLArr) { | ||
columnsHTMLArr.forEach(function (html, index) { | ||
columnsHTMLArr[index] = html.replace('</th>', '<span class="drag-lever"></span></th>') | ||
}) | ||
}), | ||
addEvent(datagrid.el, MOUSEDOWN, function (e) { | ||
if (e.target.classList.contains('drag-lever') && (IS_TOUCH || e.button === 0)) { | ||
var th = findParent('th', e.target, datagrid.el) | ||
if (!th) return | ||
if (IS_TOUCH) showDragLine(th) | ||
// 给 th 加一个状态, 避免触发排序功能 | ||
// todo 需要一个临时关闭排序的开关 | ||
th.classList.add('resizing') | ||
minLeft = -(th.clientWidth - MIN_WIDTH) | ||
draggingTH = th | ||
dragging = true | ||
startX = getPageX(e) | ||
draggingColumnIndex = indexOf.call(th.parentElement.children, th) | ||
} | ||
}), | ||
addEvent(document, MOUSEMOVE, function (e) { | ||
if (!dragging) return | ||
e.preventDefault() // 阻止在 PC 端拖动鼠标时选中文字或在移动端滑动屏幕 | ||
// 调整虚线的 left 值 | ||
var moved = getPageX(e) - startX | ||
if (moved > minLeft) { | ||
dragLine.style.left = draggingLineInitLeft + (getPageX(e) - startX) + 'px' | ||
} | ||
}), | ||
addEvent(document, MOUSEUP, function (e) { | ||
if (!dragging) return | ||
// 等 ../sort/index.js 里的 click 事件处理完后再移除这个 CSS 类 | ||
setTimeout(function () { draggingTH.classList.remove('resizing') }, 0) | ||
document.documentElement.classList.remove('data-grid-dragging') | ||
dragging = false | ||
var moved = getPageX(e) - startX // 计算移动的距离 | ||
if (moved < minLeft) moved = minLeft | ||
var columnsMinWidth = datagrid.renderData.columnsMinWidth | ||
columnsMinWidth[draggingColumnIndex] = columnsMinWidth[draggingColumnIndex] + moved | ||
datagrid.setWidth(columnsMinWidth) | ||
}) | ||
) | ||
datagrid.once('beforeDestroy', function () { | ||
unbindEvents.forEach(function (unbind) { unbind() }) | ||
}) | ||
}) | ||
} | ||
/***/ }, | ||
/* 23 */ | ||
/***/ function(module, exports) { | ||
// removed by extract-text-webpack-plugin | ||
/***/ }, | ||
/* 24 */, | ||
/* 25 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
__webpack_require__(26) | ||
var slice = Array.prototype.slice | ||
var addEvent = __webpack_require__(8) | ||
module.exports = function (DataGrid) { | ||
DataGrid.hook(function (datagrid) { | ||
if (!datagrid.options.fixedColumns) return | ||
var unbindEvents = [] | ||
var fixedDataGrid | ||
var fixedColumnsLeft | ||
datagrid.on('afterSetData', function (data) { | ||
fixedColumnsLeft = data.fixedColumnsLeft | ||
if (!fixedColumnsLeft) { | ||
if (fixedDataGrid) fixedDataGrid.el.classList.add('hidden') | ||
return | ||
} | ||
if (!fixedDataGrid) initFixedDataGrid(datagrid.el) | ||
fixedDataGrid.el.classList.remove('hidden') | ||
fixedDataGrid.setData({ | ||
columns: datagrid.renderData.columnsDef.slice(0, fixedColumnsLeft), | ||
width: datagrid.renderData.columnsWidth.slice(0, fixedColumnsLeft), | ||
rows: datagrid.renderData.rows | ||
}) | ||
// 保证 fixedDataGrid 中每一行的高度都与原 datagrid 的高度一致 | ||
var fixedGridTrs = slice.call(fixedDataGrid.ui.$columnsWrapper.querySelectorAll('tr')).concat(slice.call(fixedDataGrid.ui.$bodyWrapper.querySelectorAll('tr'))) | ||
var gridTrs = slice.call(datagrid.ui.$columnsWrapper.querySelectorAll('tr')).concat(slice.call(datagrid.ui.$bodyWrapper.querySelectorAll('tr'))) | ||
fixedGridTrs.forEach(function (tr, index) { | ||
var dTr = gridTrs[index] | ||
if (tr.clientHeight !== dTr.clientHeight) { | ||
tr.style.height = dTr.clientHeight + 'px' | ||
} | ||
}) | ||
}) | ||
datagrid.once('beforeDestroy', function () { | ||
unbindEvents.forEach(function (unbind) { | ||
unbind() | ||
}) | ||
}) | ||
function initFixedDataGrid () { | ||
var datagridContainer = document.createElement('div') | ||
datagridContainer.classList.add('fixed-datagrid') | ||
var div = document.createElement('div') | ||
div.classList.add('hidden') | ||
datagridContainer.appendChild(div) | ||
datagrid.el.appendChild(datagridContainer) | ||
fixedDataGrid = new DataGrid(div, { | ||
height: datagrid.ui.$columnsWrapper.offsetHeight + datagrid.ui.$bodyWrapper.offsetHeight, | ||
columnSorting: datagrid.options.columnSorting, | ||
columnResize: datagrid.options.columnResize, | ||
selection: datagrid.options.selection | ||
}) | ||
// 修改一个元素的 scrollTop 属性值会触发这个元素的 onscroll 事件, | ||
// 为了避免两个 datagrid 相互之间循环触发 onscroll 事件, | ||
// 所以加了下面的一堆标识位。 | ||
// 循环触发 onscroll 事件会导致在快速滑动时两个表格的 scrollTop 不同步, | ||
// 造成"撕裂"现象 | ||
var dataGridBodyScrolling = false | ||
var dataGridBodyScrollingTimeId | ||
var fixedDataGridBodyScrolling = false | ||
var fixedDataGridBodyScrollingTimeId | ||
unbindEvents.push( | ||
addEvent(datagrid.ui.$bodyWrapper, 'scroll', function () { | ||
if (fixedDataGridBodyScrolling) return | ||
dataGridBodyScrolling = true | ||
dataGridBodyScrollingTimeId && clearTimeout(dataGridBodyScrollingTimeId) | ||
dataGridBodyScrollingTimeId = setTimeout(function () { | ||
dataGridBodyScrolling = false | ||
}, 250) | ||
fixedDataGrid.ui.$bodyWrapper.scrollTop = this.scrollTop | ||
}), | ||
addEvent(fixedDataGrid.ui.$bodyWrapper, 'scroll', function () { | ||
if (dataGridBodyScrolling) return | ||
fixedDataGridBodyScrolling = true | ||
fixedDataGridBodyScrollingTimeId && clearTimeout(fixedDataGridBodyScrollingTimeId) | ||
fixedDataGridBodyScrollingTimeId = setTimeout(function () { | ||
fixedDataGridBodyScrolling = false | ||
}, 250) | ||
datagrid.ui.$bodyWrapper.scrollTop = this.scrollTop | ||
}) | ||
) | ||
unbindEvents.push( | ||
datagrid.on('trHoverTo', syncHoverIn), | ||
fixedDataGrid.on('trHoverTo', syncHoverIn), | ||
datagrid.on('clearHover', syncHoverOut), | ||
fixedDataGrid.on('clearHover', syncHoverOut) | ||
) | ||
function syncHoverIn (index, trElement) { | ||
var to = fixedDataGrid.el.contains(trElement) ? datagrid : fixedDataGrid | ||
to.trHover(true, index, false) | ||
} | ||
function syncHoverOut (index, trElement) { | ||
var to = fixedDataGrid.el.contains(trElement) ? datagrid : fixedDataGrid | ||
to.trHover(false, index, false) | ||
} | ||
if (datagrid.options.selection) { | ||
datagrid.on('selectedChanged', function (index) { | ||
fixedDataGrid.selectRow(index, false) | ||
}) | ||
fixedDataGrid.on('selectedChanged', function (index) { | ||
datagrid.selectRow(index) | ||
}) | ||
} | ||
if (datagrid.options.columnSorting) { | ||
fixedDataGrid.on('sort', function (columnDef, direction, index) { | ||
datagrid.sortBy(index) | ||
}) | ||
datagrid.on('sort', function (columnDef, direction, index) { | ||
if (index < fixedColumnsLeft) return | ||
var lastSortIndex = fixedDataGrid.sort && fixedDataGrid.sort.index | ||
if (typeof lastSortIndex === 'number') { | ||
fixedDataGrid.sort.direction = 0 | ||
var lastTh = fixedDataGrid.ui.$columnsWrapper.querySelector('th[data-index="' + lastSortIndex + '"]') | ||
if (lastTh) lastTh.classList.remove('order-by-asc', 'order-by-desc') | ||
} | ||
}) | ||
} | ||
} | ||
}) | ||
} | ||
/***/ }, | ||
/* 26 */ | ||
/***/ function(module, exports) { | ||
// removed by extract-text-webpack-plugin | ||
/***/ } | ||
/******/ ]) | ||
}); | ||
; | ||
}))); |
{ | ||
"name": "datagrid", | ||
"version": "0.3.6", | ||
"description": "Datagrid.", | ||
"main": "./src/index.js", | ||
"keywords": [ | ||
"datagrid" | ||
], | ||
"files": [ | ||
"src", | ||
"dist" | ||
], | ||
"version": "0.4.0", | ||
"description": "插件式表格组件。", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/lmk123/datagrid.git" | ||
"url": "https://github.com/lmk123/datagrid.git" | ||
}, | ||
"main": "dist/datagrid.common.js", | ||
"module": "dist/datagrid.esm.js", | ||
"unpkg": "dist/datagrid.js", | ||
"types": "declaration/index.d.ts", | ||
"files": [ | ||
"dist", | ||
"declaration" | ||
], | ||
"scripts": { | ||
"prepublish": "npm run build", | ||
"start": "webpack-dev-server --inline --config build/webpack.dev.server.config.js", | ||
"build": "webpack --config build/webpack.dev.config.js && webpack --config build/webpack.build.config.js", | ||
"lint": "eslint --ignore-pattern '/dist/' \"**/*.{js,vue}\"", | ||
"pub": "npm run lint && npm build && npm publish" | ||
"start": "node build/dev.js", | ||
"lint": "tslint -p tsconfig.json -t verbose", | ||
"build": "node build/build.js", | ||
"prepublishOnly": "npm run lint && npm run build" | ||
}, | ||
"dependencies": { | ||
"tinyemitter": "^1.0.1" | ||
}, | ||
"devDependencies": { | ||
"openpack": "1.0.0", | ||
"file-loader": "0.9.0", | ||
"postcss-loader": "1.1.1", | ||
"autoprefixer": "6.5.3", | ||
"html-loader": "0.4.4", | ||
"node-sass": "3.11.2", | ||
"sass-loader": "4.0.2", | ||
"css-loader": "0.25.0", | ||
"style-loader": "0.13.1", | ||
"html-webpack-plugin": "2.24.1", | ||
"extract-text-webpack-plugin": "1.0.1", | ||
"webpack-dev-server": "1.16.2", | ||
"webpack": "1.13.3", | ||
"eslint": "3.9.1", | ||
"eslint-plugin-html": "1.5.3", | ||
"eslint-config-standard": "6.2.1", | ||
"eslint-plugin-promise": "3.3.1", | ||
"eslint-plugin-standard": "2.0.1" | ||
"autoprefixer": "^7.2.1", | ||
"cssnano": "^3.10.0", | ||
"fs-extra": "^4.0.2", | ||
"postcss-cssnext": "^3.0.2", | ||
"rollup": "^0.50.1", | ||
"rollup-plugin-buble": "^0.18.0", | ||
"rollup-plugin-html": "^0.2.1", | ||
"rollup-plugin-livereload": "^0.6.0", | ||
"rollup-plugin-node-resolve": "^3.0.0", | ||
"rollup-plugin-postcss": "^0.5.5", | ||
"rollup-plugin-serve": "^0.4.2", | ||
"rollup-plugin-typescript2": "^0.8.1", | ||
"rollup-watch": "^4.3.1", | ||
"tslint": "^5.8.0", | ||
"tslint-config-prettier": "^1.6.0", | ||
"tslint-config-standard": "^7.0.0", | ||
"typescript": "^2.6.1", | ||
"uglify-js": "^3.1.10" | ||
}, | ||
"author": "Milk Lee <milk.lee@qq.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/lmk123/datagrid/issues" | ||
}, | ||
"homepage": "https://github.com/lmk123/datagrid#readme" | ||
"license": "MIT" | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
124422
2511
1
212
0
1
16
3
2
1
+ Addedtinyemitter@^1.0.1
+ Addedtinyemitter@1.0.1(transitive)