forked from JavaScript/bee-table
423 lines
12 KiB
JavaScript
423 lines
12 KiB
JavaScript
import warning from 'warning';
|
||
import parseInt from 'lodash/parseInt';
|
||
|
||
|
||
let scrollbarSize;
|
||
|
||
// Measure scrollbar width for padding body during modal show/hide
|
||
const scrollbarMeasure = {
|
||
position: 'absolute',
|
||
top: '-9999px',
|
||
width: '50px',
|
||
height: '50px',
|
||
overflow: 'scroll',
|
||
};
|
||
|
||
export function measureScrollbar(direction = 'vertical') {
|
||
|
||
if (typeof document === 'undefined' || typeof window === 'undefined') {
|
||
return 0;
|
||
}
|
||
const tableDom =document.querySelector('.u-table');
|
||
let currentDom = tableDom?tableDom:document.body;
|
||
|
||
if (scrollbarSize) {
|
||
return scrollbarSize;
|
||
}
|
||
const scrollDiv = document.createElement('div');
|
||
Object.keys(scrollbarMeasure).forEach(scrollProp => {
|
||
scrollDiv.style[scrollProp] = scrollbarMeasure[scrollProp];
|
||
});
|
||
currentDom.appendChild(scrollDiv);
|
||
let size = 0;
|
||
if (direction === 'vertical') {
|
||
size = scrollDiv.offsetWidth - scrollDiv.clientWidth;
|
||
} else if (direction === 'horizontal') {
|
||
size = scrollDiv.offsetHeight - scrollDiv.clientHeight;
|
||
}
|
||
|
||
currentDom.removeChild(scrollDiv);
|
||
scrollbarSize = size;
|
||
return scrollbarSize;
|
||
}
|
||
|
||
export function myBrowser() {
|
||
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
|
||
var isOpera = userAgent.indexOf("Opera") > -1;
|
||
if (isOpera) { //判断是否Opera浏览器
|
||
return "Opera"
|
||
}
|
||
if (userAgent.indexOf("Firefox") > -1) { //判断是否Firefox浏览器
|
||
return "FF";
|
||
}
|
||
if (userAgent.indexOf("Chrome") > -1) {
|
||
return "Chrome";
|
||
}
|
||
if (userAgent.indexOf("Safari") > -1) { //判断是否Safari浏览器
|
||
return "Safari";
|
||
}
|
||
if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) { //判断是否IE浏览器
|
||
return "IE";
|
||
}
|
||
}
|
||
|
||
export function debounce(func, wait, immediate) {
|
||
let timeout;
|
||
return function debounceFunc() {
|
||
const context = this;
|
||
const args = arguments;
|
||
// https://fb.me/react-event-pooling
|
||
if (args[0] && args[0].persist) {
|
||
args[0].persist();
|
||
}
|
||
const later = () => {
|
||
timeout = null;
|
||
if (!immediate) {
|
||
func.apply(context, args);
|
||
}
|
||
};
|
||
const callNow = immediate && !timeout;
|
||
clearTimeout(timeout);
|
||
timeout = setTimeout(later, wait);
|
||
if (callNow) {
|
||
func.apply(context, args);
|
||
}
|
||
};
|
||
}
|
||
|
||
const warned = {};
|
||
export function warningOnce(condition, format, args) {
|
||
if (!warned[format]) {
|
||
warning(condition, format, args);
|
||
warned[format] = true;
|
||
}
|
||
}
|
||
export function getOffset (Node, offset ) {
|
||
if(!offset) {
|
||
offset = {};
|
||
offset.top = 0;
|
||
offset.left = 0;
|
||
}
|
||
if(Node == document.body) {
|
||
return offset;
|
||
}
|
||
offset.top += Node.offsetTop;
|
||
offset.left += Node.offsetLeft;
|
||
if(Node.offsetParent)
|
||
return getOffset(Node.offsetParent, offset);
|
||
else
|
||
return offset;
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
export const tryParseInt = (value, defaultValue = 0) => {
|
||
const resultValue = parseInt(value);
|
||
|
||
if (isNaN(resultValue)) {
|
||
return defaultValue;
|
||
}
|
||
return resultValue;
|
||
};
|
||
|
||
|
||
export function addClass(elm, className) {
|
||
if (!className) return;
|
||
|
||
const els = Array.isArray(elm) ? elm : [elm];
|
||
|
||
els.forEach((el) => {
|
||
if (el.classList) {
|
||
el.classList.add(className.split(' '));
|
||
} else {
|
||
el.className += ` ${className}`;
|
||
}
|
||
});
|
||
}
|
||
|
||
export function removeClass(elm, className) {
|
||
if (!className) return;
|
||
|
||
const els = Array.isArray(elm) ? elm : [elm];
|
||
|
||
els.forEach((el) => {
|
||
if (el.classList) {
|
||
el.classList.remove(className.split(' '));
|
||
} else {
|
||
el.className = el.className.replace(new RegExp(`(^|\\b)${className.split(' ').join('|')}(\\b|$)`, 'gi'), ' ');
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 简单数组数据对象拷贝
|
||
* @param {*} obj 要拷贝的对象
|
||
*/
|
||
export function ObjectAssign(obj){
|
||
let b = obj instanceof Array;
|
||
let tagObj = b?[]:{};
|
||
if(b){//数组
|
||
obj.forEach(da => {
|
||
let _da = {};
|
||
Object.assign(_da,da);
|
||
tagObj.push(_da);
|
||
});
|
||
}else{
|
||
Object.assign(tagObj,obj);
|
||
}
|
||
return tagObj;
|
||
}
|
||
/**
|
||
* 获取某个父元素
|
||
* */
|
||
|
||
export function closest(ele, selector) {
|
||
const matches = ele.matches || ele.webkitMatchesSelector || ele.mozMatchesSelector || ele.msMatchesSelector;
|
||
if (matches) {
|
||
while (ele) {
|
||
if (matches.call(ele, selector)) {
|
||
return ele;
|
||
} else {
|
||
ele = ele.parentElement;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
|
||
export function getMaxColChildrenLength(columns){
|
||
let arr=[];
|
||
arr = columns.map((item,index)=>{
|
||
let chilrenLen = 0;
|
||
if(item.children){
|
||
chilrenLen = getColChildrenLength(item.children,chilrenLen+1)
|
||
}
|
||
return chilrenLen
|
||
})
|
||
var max = Math.max.apply(null,arr);
|
||
return max;
|
||
}
|
||
|
||
export function getColChildrenLength(columns,chilrenLen){
|
||
columns.forEach((item,index)=>{
|
||
if(item.children){
|
||
chilrenLen = getColChildrenLength(item.children,chilrenLen+1);
|
||
}
|
||
})
|
||
return chilrenLen;
|
||
}
|
||
|
||
|
||
function addHandler(element,type,handler){
|
||
let event = null;
|
||
if(element.addEventListener){//检测是否为DOM2级方法
|
||
event = element.addEventListener(type, handler, false);
|
||
}else if (element.attachEvent){//检测是否为IE级方法
|
||
event = element.attachEvent("on" + type, handler);
|
||
} else {//检测是否为DOM0级方法
|
||
event = element["on" + type] = handler;
|
||
}
|
||
return event;
|
||
}
|
||
|
||
function removeHandler(element, type, handler){
|
||
if (element&&element.removeEventListener){//element&& ie11报错兼容
|
||
element.removeEventListener(type, handler, false);
|
||
} else if (element&&element.detachEvent){
|
||
element.detachEvent("on" + type, handler);
|
||
} else if(element) {
|
||
element["on" + type] = null;
|
||
}
|
||
}
|
||
|
||
//获取事件对象的兼容性写法
|
||
function getEvent(event){
|
||
return event ? event : window.event;
|
||
}
|
||
|
||
//获取事件对象目标的兼容性写法
|
||
function getTarget(event){
|
||
return event.target || event.srcElement;
|
||
}
|
||
|
||
function preventDefault(event){
|
||
if (event.preventDefault){
|
||
event.preventDefault();
|
||
} else {
|
||
event.returnValue = false;
|
||
}
|
||
}
|
||
|
||
function stopPropagation(event){
|
||
if (event.stopPropagation){
|
||
event.stopPropagation();
|
||
} else {
|
||
event.cancelBubble = true;
|
||
}
|
||
}
|
||
|
||
|
||
//用事件冒泡方式,如果想兼容事件捕获只需要添加个bool参数
|
||
export const EventUtil = {
|
||
addHandler: function(element,type,handler) {
|
||
if (element.addEventListener) {
|
||
element.addEventListener(type,handler,false);
|
||
}
|
||
else if (element.attachEvent) {
|
||
element.attachEvent('on'+type,handler);
|
||
}
|
||
else {
|
||
element['on'+type] = handler;
|
||
}
|
||
},
|
||
|
||
removeHandler: function(element,type,handler) {//element&& ie11报错兼容
|
||
if (element&&element.removeEventListener)
|
||
{
|
||
element.removeEventListener(type,handler,false);
|
||
}
|
||
else if(element&&element.detachEvent) {
|
||
element.detachEvent('on' +type,handler);
|
||
}
|
||
else if(element){
|
||
element['on'+type] = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 处理精度
|
||
*/
|
||
export function DicimalFormater(value,precision) {
|
||
var value = value + '',
|
||
precision = precision?precision:0;
|
||
for (var i = 0; i < value.length; i++) {
|
||
if ("-0123456789.".indexOf(value.charAt(i)) == -1)
|
||
return "";
|
||
}
|
||
return checkDicimalInvalid(value, precision);
|
||
};
|
||
export function checkDicimalInvalid(value, precision) {
|
||
if (value == null || isNaN(value))
|
||
return "";
|
||
// 浮点数总位数不能超过10位
|
||
var digit = parseFloat(value);
|
||
var result = (digit * Math.pow(10, precision) / Math.pow(10, precision))
|
||
.toFixed(precision);
|
||
if (result == "NaN")
|
||
return "";
|
||
return result;
|
||
};
|
||
|
||
|
||
/**
|
||
* 将数值转化为货币类型
|
||
* @param {*} number 数值
|
||
* @param {*} places 精度
|
||
* @param {*} thousand 是否展示千分位
|
||
*/
|
||
export function formatMoney(number, places, thousand) {
|
||
number = number || 0;
|
||
places = !isNaN(places = Math.abs(places)) ? places : 2;
|
||
let thousandSymbol = thousand ? "," : '';
|
||
let negative = number < 0 ? "-" : "";
|
||
let i = parseInt(number = Math.abs(+number || 0).toFixed(places), 10) + "";
|
||
let j = (j = i.length) > 3 ? j % 3 : 0;
|
||
return negative + (j ? i.substr(0, j) + thousandSymbol : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousandSymbol) + (places ? '.' + Math.abs(number - i).toFixed(places).slice(2) : "");
|
||
}
|
||
|
||
export const Event = {
|
||
addHandler,
|
||
removeHandler,
|
||
getEvent,
|
||
getTarget,
|
||
preventDefault,
|
||
stopPropagation
|
||
}
|
||
|
||
/**
|
||
* 将一维数组转换为树结构
|
||
* @param {*} treeData 扁平结构的 List 数组
|
||
* @param {*} attr 属性配置设置
|
||
* @param {*} flatTreeKeysMap 存储所有 key-value 的映射,方便获取各节点信息
|
||
*/
|
||
export function convertListToTree(treeData, attr, flatTreeKeysMap) {
|
||
let tree = []; //存储所有一级节点
|
||
let resData = treeData, //resData 存储截取的节点 + 父节点(除一级节点外)
|
||
resKeysMap = {}, //resData 的Map映射
|
||
treeKeysMap = {}; //tree 的Map映射
|
||
resData.map((element) => {
|
||
let key = attr.id;
|
||
resKeysMap[element[key]] = element;
|
||
});
|
||
// 查找父节点,为了补充不完整的数据结构
|
||
let findParentNode = (node) => {
|
||
let parentKey = node[attr.parendId];
|
||
if(parentKey !== attr.rootId) { //如果不是根节点,则继续递归
|
||
let item = flatTreeKeysMap[parentKey];
|
||
// 用 resKeysMap 判断,避免重复计算某节点的父节点
|
||
if(resKeysMap.hasOwnProperty(item[attr.id])) return;
|
||
resData.unshift(item);
|
||
resKeysMap[item[attr.id]] = item;
|
||
findParentNode(item);
|
||
}else{
|
||
// 用 treeKeysMap 判断,避免重复累加
|
||
if (!treeKeysMap.hasOwnProperty(node[attr.id]) ) {
|
||
let { key, title, children, _isLeaf, ...otherProps } = node;
|
||
let obj = {
|
||
key,
|
||
title,
|
||
_isLeaf,
|
||
children: []
|
||
}
|
||
tree.push(Object.assign(obj, {...otherProps}));
|
||
treeKeysMap[key] = node;
|
||
}
|
||
}
|
||
}
|
||
// 遍历 resData ,找到所有的一级节点
|
||
for (let i = 0; i < resData.length; i++) {
|
||
let item = resData[i];
|
||
if (item[attr.parendId] === attr.rootId && !treeKeysMap.hasOwnProperty(item[attr.id])) { //如果是根节点,就存放进 tree 对象中
|
||
let { key, title, children, ...otherProps } = item;
|
||
let obj = {
|
||
key: item[attr.id],
|
||
_isLeaf: item[attr._isLeaf],
|
||
children: []
|
||
};
|
||
tree.push(Object.assign(obj, {...otherProps}));
|
||
treeKeysMap[key] = item;
|
||
resData.splice(i, 1);
|
||
i--;
|
||
}else { //递归查找根节点信息
|
||
findParentNode(item);
|
||
}
|
||
}
|
||
// console.log('resData',resKeysMap);
|
||
var run = function(treeArrs) {
|
||
if (resData.length > 0) {
|
||
for (let i = 0; i < treeArrs.length; i++) {
|
||
for (let j = 0; j < resData.length; j++) {
|
||
let item = resData[j];
|
||
if (treeArrs[i].key === item[attr.parendId]) {
|
||
let { key, title, children, ...otherProps } = item;
|
||
let obj = {
|
||
key: item[attr.id],
|
||
_isLeaf: item[attr._isLeaf],
|
||
children: []
|
||
};
|
||
treeArrs[i].children.push(Object.assign(obj, {...otherProps}));
|
||
resData.splice(j, 1);
|
||
j--;
|
||
}
|
||
}
|
||
run(treeArrs[i].children);
|
||
}
|
||
}
|
||
};
|
||
run(tree);
|
||
return tree;
|
||
} |