71 lines
2.2 KiB
JavaScript
Executable File
71 lines
2.2 KiB
JavaScript
Executable File
import { svgTextDraw } from './svg-text-draw.js';
|
|
import { svgEl } from './util.js';
|
|
|
|
/**
|
|
* Create teaxtArea above SVGTextElement 'textEl'
|
|
* update 'textEl' with text from teaxtArea
|
|
* resize teaxtArea - so teaxtArea always cover all 'textEl'
|
|
* @param {SVGTextElement} textEl
|
|
* @param {number} verticalMiddle em
|
|
* @param {string} val
|
|
* @param {{(val:string):void}} onchange
|
|
* @param {{(val:string):void}} onblur
|
|
*/
|
|
export function textareaCreate(textEl, verticalMiddle, val, onchange, onblur) {
|
|
let foreign = svgEl('foreignObject');
|
|
const textarea = document.createElement('textarea');
|
|
const draw = () => foreignWidthSet(textEl, foreign, textarea, textareaPaddingAndBorder, textareaStyle.textAlign);
|
|
|
|
textarea.value = val || '';
|
|
textarea.oninput = function() {
|
|
svgTextDraw(textEl, verticalMiddle, textarea.value);
|
|
onchange(textarea.value);
|
|
draw();
|
|
};
|
|
textarea.onblur = function() {
|
|
onblur(textarea.value);
|
|
};
|
|
textarea.onpointerdown = function(evt) {
|
|
evt.stopImmediatePropagation();
|
|
};
|
|
|
|
foreign.appendChild(textarea);
|
|
textEl.parentElement.appendChild(foreign);
|
|
|
|
const textareaStyle = getComputedStyle(textarea);
|
|
// must be in px
|
|
const textareaPaddingAndBorder = parseInt(textareaStyle.paddingLeft) + parseInt(textareaStyle.borderWidth);
|
|
draw();
|
|
|
|
textarea.focus();
|
|
|
|
return {
|
|
dispose: () => { foreign.remove(); foreign = null; },
|
|
draw
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {SVGTextElement} textEl
|
|
* @param {SVGForeignObjectElement} foreign
|
|
* @param {HTMLTextAreaElement} textarea
|
|
* @param {number} textareaPaddingAndBorder
|
|
* @param {string} textAlign
|
|
*/
|
|
function foreignWidthSet(textEl, foreign, textarea, textareaPaddingAndBorder, textAlign) {
|
|
const textBbox = textEl.getBBox();
|
|
const width = textBbox.width + 20; // +20 paddings for iPhone
|
|
|
|
foreign.width.baseVal.value = width + 2 * textareaPaddingAndBorder + 2; // +2 magic number for FireFox
|
|
foreign.x.baseVal.value = textBbox.x - textareaPaddingAndBorder - (
|
|
textAlign === 'center'
|
|
? 10
|
|
: textAlign === 'right' ? 20 : 0);
|
|
|
|
foreign.height.baseVal.value = textBbox.height + 2 * textareaPaddingAndBorder + 3; // +3 magic number for FireFox
|
|
foreign.y.baseVal.value = textBbox.y - textareaPaddingAndBorder;
|
|
|
|
textarea.style.width = `${width}px`;
|
|
textarea.style.height = `${textBbox.height}px`;
|
|
}
|