butterfly-dag
Version:
一个基于数据驱动的节点式编排组件库,让你有方便快捷定制可视化流程图表
265 lines (246 loc) • 6.53 kB
JavaScript
const $ = require('jquery');
const _ = require('lodash');
import Node from '../interface/node';
import Endpoint from '../endpoint/baseEndpoint';
class BaseNode extends Node {
constructor(opts) {
super(opts);
this.id = opts.id;
this.scope = opts.scope;
this.group = opts.group;
this.top = opts.top || 0;
this.left = opts.left || 0;
this.dom = opts.dom || null;
this.draggable = opts.draggable;
this.options = opts;
// 鸭子辨识手动判断类型
this.__type = 'node';
this._on = opts._on;
this._emit = opts._emit;
this._global = opts._global;
// endpoint 这部分需要考虑
this.endpoints = [];
this._endpointsData = opts.endpoints;
this._endpointLimitNum = opts._endpointLimitNum;
// 标识是否在移动做,兼容冒泡
this._isMoving = false;
// 长宽
this.width = undefined;
this.height = undefined;
this._isForceUpdateSize = false;
}
draw(obj) {
let _dom = obj.dom;
if (!_dom) {
_dom = $('<div></div>')
.attr('class', 'node')
.attr('id', obj.id);
}
const node = $(_dom);
if (obj.top !== undefined) {
node.css('top', `${obj.top}px`);
}
if (obj.left !== undefined) {
node.css('left', `${obj.left}px`);
}
this.updated && this.updated();
return node[0];
}
focus() {}
unFocus() {}
addEndpoint(obj, isInited) {
if (isInited) {
this.emit('InnerEvents', {
type: 'node:addEndpoint',
data: obj,
isInited
});
return obj;
}
// 这部分可能还需要想一下
const EndpointClass = obj.Class || Endpoint;
const endpoint = new EndpointClass(_.assign({
limitNum: obj.limitNum || this._endpointLimitNum,
_on: this._on,
_emit: this._emit,
_node: this,
_global: this.global
}, obj));
this.emit('InnerEvents', {
type: 'node:addEndpoint',
data: endpoint
});
this.endpoints.push(endpoint);
return endpoint;
}
removeEndpoint(pointId) {
const rmEndpointIndex = _.findIndex(this.endpoints, point => point.id === pointId);
if (rmEndpointIndex !== -1) {
const rmEndpoint = this.endpoints.splice(rmEndpointIndex, 1)[0];
this.emit('InnerEvents', {
type: 'node:removeEndpoint',
data: rmEndpoint
});
rmEndpoint.destroy();
return rmEndpoint;
}
}
getEndpoint(pointId, type) {
return _.find(this.endpoints, (point) => {
if (!point.type || point.type === 'onlyConnect') {
return pointId === point.id;
} else {
return pointId === point.id && ((type && type === point.type) || !type);
}
});
}
_init(obj = {}) {
if (this._isInited) {
return;
}
// 这里可以抽象下,和constructor对比
if (obj.left) {
this.left = obj.left;
}
if (obj.top) {
this.top = obj.top;
}
if (obj._isDeleteGroup) {
this.group = undefined;
this._group = undefined;
} else {
obj.group && (this.group = obj.group);
}
delete obj._isDeleteGroup;
this._isInited = true;
if (obj.dom) {
this.dom = obj.dom;
obj.left && ($(this.dom).css('left', `${obj.left}px`));
obj.top && ($(this.dom).css('top', `${obj.top}px`));
} else {
this.dom = this.draw(_.assign({
id: this.id,
top: this.top,
left: this.left,
dom: this.dom,
options: this.options
}, obj));
}
if (!this._hasEventListener) {
this._addEventListener();
this._hasEventListener = true;
}
}
// drag的时候移动的api
_moveTo(x, y) {
// 自身移动
$(this.dom).css('top', y).css('left', x);
// 所在的点移动
this.endpoints.forEach((item) => {
item.moveTo(x - this.left + item._left, y - this.top + item._top);
});
this.top = y;
this.left = x;
}
moveTo(x, y, isNotEventEmit) {
this.emit('InnerEvents', {
type: 'node:move',
node: this,
x,
y,
isNotEventEmit
});
}
getWidth(useCache) {
if (!useCache || !this.width || this._isForceUpdateSize) {
this.width = $(this.dom).outerWidth();
this._isForceUpdateSize = false;
}
return this.width;
}
getHeight(useCache) {
if (!useCache || !this.height || this._isForceUpdateSize) {
this.height = $(this.dom).outerHeight();
this._isForceUpdateSize = false;
}
return this.height;
}
_createEndpoint(isInited) {
if (isInited) {
this.endpoints.forEach(item => this.addEndpoint(item, isInited));
} else if (this._endpointsData) {
this._endpointsData.map(item => this.addEndpoint(item));
}
}
_addEventListener() {
// todo 做事件代理的形式
$(this.dom).on('mousedown', (e) => {
const LEFT_KEY = 0;
if (e.button !== LEFT_KEY) {
return;
}
if (!['SELECT', 'INPUT', 'RADIO', 'CHECKBOX', 'TEXTAREA'].includes(e.target.nodeName)) {
e.preventDefault();
}
if (this.draggable) {
this._isMoving = true;
this.emit('InnerEvents', {
type: 'node:dragBegin',
data: this
});
} else {
// 单纯为了抛错事件给canvas,为了让canvas的dragtype不为空,不会触发canvas:click事件
this.emit('InnerEvents', {
type: 'node:mouseDown',
data: this
});
}
});
$(this.dom).on('click', (e) => {
e.preventDefault();
e.stopPropagation();
this.emit('system.node.click', {
node: this
});
this.emit('events', {
type: 'node:click',
node: this
});
});
this.setDraggable(this.draggable);
}
setDraggable(draggable) {
this.draggable = draggable;
}
remove() {
this.emit('InnerEvents', {
type: 'node:delete',
data: this
});
}
emit(type, data) {
super.emit(type, data);
this._emit(type, data);
}
on(type, callback) {
super.on(type, callback);
this._on(type, callback);
}
destroy(isNotEvent) {
if (!isNotEvent) {
this.endpoints.forEach((item) => {
!item._isInitedDom && item.destroy();
});
$(this.dom).remove();
this.removeAllListeners();
this._hasEventListener = false;
} else {
this.endpoints.forEach((item) => {
!item._isInitedDom && item.destroy(isNotEvent);
});
$(this.dom).detach();
}
this._isInited = false;
}
}
export default BaseNode;