@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering.
185 lines • 6.16 kB
JavaScript
import { ToolsView } from '../../view/tool';
import { Point } from '../../geometry';
import { Dom, FunctionExt } from '../../util';
export class CellEditor extends ToolsView.ToolItem {
constructor() {
super(...arguments);
this.labelIndex = -1;
this.distance = 0.5;
}
render() {
this.createElement();
this.update();
this.autoFocus();
this.delegateDocumentEvents(this.options.documentEvents);
return this;
}
createElement() {
const { cell } = this;
const classNames = [
this.prefixClassName(`${cell.isEdge() ? 'edge' : 'node'}-tool-editor`),
this.prefixClassName('cell-tool-editor'),
];
this.editor = ToolsView.createElement('div', false);
this.addClass(classNames, this.editor);
this.editor.contentEditable = 'true';
this.container.appendChild(this.editor);
}
update() {
const { graph, cell, editor } = this;
const style = editor.style;
// set tool position
let pos = new Point();
let minWidth = 20;
if (cell.isNode()) {
pos = cell.getBBox().center;
minWidth = cell.size().width - 4;
}
else if (cell.isEdge()) {
const e = this.options.event;
const target = e.target;
const parent = target.parentElement;
const isEdgeLabel = parent && Dom.hasClass(parent, this.prefixClassName('edge-label'));
if (isEdgeLabel) {
const index = parent.getAttribute('data-index') || '0';
this.labelIndex = parseInt(index, 10);
const matrix = parent.getAttribute('transform');
const { translation } = Dom.parseTransformString(matrix);
pos = new Point(translation.tx, translation.ty);
minWidth = Dom.getBBox(target).width;
}
else {
pos = graph.clientToLocal(Point.create(e.clientX, e.clientY));
const view = this.cellView;
const d = view.path.closestPointLength(pos);
this.distance = d;
}
}
pos = graph.localToGraph(pos);
style.left = `${pos.x}px`;
style.top = `${pos.y}px`;
style.minWidth = `${minWidth}px`;
// set tool transform
const scale = graph.scale();
style.transform = `scale(${scale.sx}, ${scale.sy}) translate(-50%, -50%)`;
// set font style
const attrs = this.options.attrs;
style.fontSize = `${attrs.fontSize}px`;
style.fontFamily = attrs.fontFamily;
style.color = attrs.color;
style.backgroundColor = attrs.backgroundColor;
// set init value
const getText = this.options.getText;
let text;
if (typeof getText === 'function') {
text = FunctionExt.call(getText, this.cellView, {
cell: this.cell,
index: this.labelIndex,
});
}
editor.innerText = text || '';
return this;
}
onDocumentMouseDown(e) {
if (e.target !== this.editor) {
const cell = this.cell;
const value = this.editor.innerText.replace(/\n$/, '') || '';
// set value
const setText = this.options.setText;
if (typeof setText === 'function') {
FunctionExt.call(setText, this.cellView, {
cell: this.cell,
value,
index: this.labelIndex,
distance: this.distance,
});
}
// remove tool
cell.removeTool(cell.isEdge() ? 'edge-editor' : 'node-editor');
this.undelegateDocumentEvents();
}
}
onDblClick(e) {
e.stopPropagation();
}
onMouseDown(e) {
e.stopPropagation();
}
autoFocus() {
setTimeout(() => {
this.editor.focus();
this.selectText();
});
}
selectText() {
if (window.getSelection) {
const range = document.createRange();
const selection = window.getSelection();
range.selectNodeContents(this.editor);
selection.removeAllRanges();
selection.addRange(range);
}
}
}
(function (CellEditor) {
CellEditor.config({
tagName: 'div',
isSVGElement: false,
events: {
dblclick: 'onDblClick',
mousedown: 'onMouseDown',
},
documentEvents: {
mousedown: 'onDocumentMouseDown',
},
});
})(CellEditor || (CellEditor = {}));
(function (CellEditor) {
CellEditor.NodeEditor = CellEditor.define({
attrs: {
fontSize: 14,
fontFamily: 'Arial, helvetica, sans-serif',
color: '#000',
backgroundColor: '#fff',
},
getText({ cell }) {
return cell.attr('text/text');
},
setText({ cell, value }) {
cell.attr('text/text', value);
},
});
CellEditor.EdgeEditor = CellEditor.define({
attrs: {
fontSize: 14,
fontFamily: 'Arial, helvetica, sans-serif',
color: '#000',
backgroundColor: '#fff',
},
getText({ cell, index }) {
if (index === -1) {
return '';
}
return cell.prop(`labels/${index}/attrs/label/text`);
},
setText({ cell, value, index, distance }) {
const edge = cell;
if (index === -1) {
edge.appendLabel({
position: {
distance: distance,
},
attrs: {
label: {
text: value,
},
},
});
}
else {
edge.prop(`labels/${index}/attrs/label/text`, value);
}
},
});
})(CellEditor || (CellEditor = {}));
//# sourceMappingURL=editor.js.map