import { on, off, createEl, stopPropagation } from '../../core/util/dom'; import { isNil } from '../../core/util'; import TextMarker from '../../geometry/TextMarker'; import UIMarker from '../../ui/UIMarker'; /** * Mixin methods for text editing. * @mixin TextEditable */ const TextEditable = { /** * 开始编辑文本,每当点击地图时,编辑将自动结束 * @english * Start to edit the text, editing will be ended automatically whenever map is clicked. * * @return {TextMarker} this * @fires TextMarker#edittextstart */ startEditText(): TextMarker { if (!this.getMap()) { return this; } this._recordVisible(); this.hide(); this.endEditText(); this._prepareEditor(); /** * edittextstart when starting to edit text content * @event TextMarker#edittextstart * @type {Object} * @property {String} type - edittextstart * @property {TextMarker} target - fires the event */ this._fireEvent('edittextstart'); return this; }, /** * 结束编辑 * @english * End text edit. * * @return {TextMarker} this * @fires TextMarker#edittextend */ endEditText() { if (this._textEditor) { let html = this._textEditor.innerHTML; html = html.replace(/
/ig, '').replace(/<\/p>/ig, '
');
this._textEditor.innerHTML = html;
// trim enter chars in the end of text for IE
const content = this._textEditor.innerText.replace(/[\r\n]+$/gi, '');
this.setContent(content);
off(this._textEditor, 'mousedown dblclick', stopPropagation);
this.getMap().off('mousedown', this.endEditText, this);
this._editUIMarker.remove();
delete this._editUIMarker;
this._textEditor.onkeyup = null;
delete this._textEditor;
this._recoveryVisible();
this.show();
/**
* edittextend when ended editing text content
* @event TextMarker#edittextend
* @type {Object}
* @property {String} type - edittextend
* @property {TextMarker} target - textMarker fires the event
*/
this._fireEvent('edittextend');
}
return this;
},
/**
* 是否正在编辑文本
* @english
* Whether the text is being edited.
*
* @return {Boolean}
*/
isEditingText() {
if (this._textEditor) {
return true;
}
return false;
},
/**
* 获取正在编辑的文本对象
* @english
* Get the text editor which is an [ui.UIMarker]{@link ui.UIMarker}
* @return {ui.UIMarker} text editor
*/
getTextEditor(): UIMarker {
return this._editUIMarker;
},
//@internal
_prepareEditor(): void {
const map = this.getMap();
const editContainer = this._createEditor();
this._textEditor = editContainer;
map.on('mousedown', this.endEditText, this);
const offset = this._getEditorOffset();
this._editUIMarker = new UIMarker(this.getCoordinates(), {
'animation': null,
'content': editContainer,
'dx': offset.dx,
'dy': offset.dy
})
.addTo(map);
this._setCursorToLast(this._textEditor);
},
//@internal
_getEditorOffset(): object {
const symbol = this._getInternalSymbol() || {};
let dx = 0,
dy = 0;
const textAlign = symbol['textHorizontalAlignment'];
if (textAlign === 'middle' || isNil(textAlign)) {
dx = (symbol['textDx'] || 0) - 2;
dy = (symbol['textDy'] || 0) - 2;
} else {
dx = (symbol['markerDx'] || 0) - 2;
dy = (symbol['markerDy'] || 0) - 2;
}
return {
'dx': dx,
'dy': dy
};
},
//@internal
_createEditor(): HTMLElement {
const content = this.getContent();
const labelSize = this.getSize(),
symbol = this._getInternalSymbol() || {},
width = labelSize.width,
textColor = symbol['textFill'] || '#000000',
textSize = symbol['textSize'] || 12,
height = labelSize.height,
lineColor = symbol['markerLineColor'] || '#000',
fill = symbol['markerFill'] || '#3398CC',
spacing = symbol['textLineSpacing'] || 0;
const editor = createEl('div');
// @ts-expect-error todo
editor.contentEditable = true;
editor.style.cssText = `background:${fill}; border:1px solid ${lineColor};
color:${textColor};font-size:${textSize}px;width:${width - 2}px;height:${height - 2}px;margin: auto;
line-height:${textSize + spacing}px;outline: 0; padding:0; margin:0;word-wrap: break-word;
overflow: hidden;-webkit-user-modify: read-write-plaintext-only;`;
editor.innerText = content;
on(editor, 'mousedown dblclick', stopPropagation);
editor.onkeyup = function (event) {
const h: any = editor.style.height || 0;
if (event.keyCode === 13) {
editor.style.height = (parseInt(h) + textSize / 2) + 'px';
}
};
return editor;
},
//@internal
_setCursorToLast(obj) {
let range;
if (window.getSelection) {
obj.focus();
range = window.getSelection();
range.selectAllChildren(obj);
range.collapseToEnd();
// @ts-expect-error todo待确认document
} else if (document.selection) {
// @ts-expect-error todo待确认document
range = document.selection.createRange();
range.moveToElementText(obj);
range.collapse(false);
range.select();
}
}
};
TextMarker.include(TextEditable);
export default TextEditable;