JavaScript text editor for SVG
Tags: javascript, webdev, html, tutorial
Published: 2022-04-22 15:41:41


![SVG text editor with support for selection, copy, paste. Works on PC and mobile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uc3h0qycptvo4025nvx4.gif)
_Fig 1. SVG text editor with support for selection, copy, paste. Works on PC and mobile._

[Demo](https://dgrm.net/) | [GitHub](https://github.com/AlexeyBoiko/)

The article describes how to make a text editor. Source code is attached.

## Multiline text in SVG

SVG does not have a line break character. For multiline text SVG uses `<tspan>`.

![Multiline text, third line is empty](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dd63b4fde7qy18nkynaq.png)
_Fig 2. Multiline text, third line is empty_

```html
<text x="0" y="0">
    <tspan x="0" y="0">Line 1</tspan>
    <tspan x="0" y="20px">Line 2</tspan>
    <!-- Line 3 is empty
    <tspan x="0" y="40px"></tspan> -->
    <tspan x="0" y="60px">Line 4</tspan>
</text>
```
_Listing 1. Multiline text in SVG. The third line is empty. The line height is 20px._

The position of the `<tspan>` elements is relative to the top edge of the `<text>`. The value of the 'y' attribute must be calculated.

The 'y' attribute calculations can be avoided. Listing 2 gives the same result. The 'dy' attribute is used with a fixed value. 'dy' indicates the position relative to the previous element.

```html
<text x="0" y="0">
    <tspan x="0" dy="0">Line 1</tspan>
    <tspan x="0" dy="20px">Line 2</tspan>
    <tspan x="0" dy="20px" visibility="hidden">.</tspan>
    <tspan x="0" dy="20px">Line 4</tspan>
</text>
```
_Listing 2. Multiline text in SVG. The third line is empty. The line height is 20px. The indent is set relative to the previous element._

## Forming multi-line markup with JavaScript
The function below renders markup with a fixed 'dy' attribute. The markup is obtained as in Listing 2.
```js
/**
 * create multiline tspan markup
 * @param {string} str
 * @param {number} lineHeight
 * @returns {string}
 */
function svgStrToTspan(str, lineHeight) {
    return str.split('\n').map((t, i) => {
        return `<tspan
            x="0"
            dy="${i === 0 ? '0' : `${lineHeight}px`}"
            ${t.length === 0 ? 'visibility="hidden"' : ''}>
 
                ${t.length === 0
                    ? '.'
                    : escapeHtml(t).replaceAll(' ', '&nbsp;')}
 
            </tspan>`;
    }).join('');
}
```
_Listing 3. Function makes multi-line markup_

In Figure 1, when you add a line, the text moves up. Thus the text is always in the center of the circle. Listing 4 shows how this is implemented:

```js
/**
 * @param {SVGTextElement} textEl target text element
 * @param {string} str
 * @param {{lineHeight:number, verticalMiddle?:number}} param
 * @returns {void}
 */
export function svgTextDraw(textEl, str, param) {
    textEl.innerHTML = svgStrToTspan(str, param.lineHeight);
    if (param.verticalMiddle != null) {
        textEl.y.baseVal[0].value =
            param.verticalMiddle - textEl.getBBox().height / 2;
    }
}
```
_Listing 4. The function inserts text into SVG. When specifying verticalMiddle , the text is centered vertically._

## Text editor
The editor must support all standard features:
 - text navigation, selection, insertion, copying;
 - autocorrect, spell check;
 - work on PC and mobile

For standard features, there is a standard `<textarea>`.

The algorithm of the editor:
 - A transparent `<textarea>` is positioned above the text.  
The `<textarea>` font is also transparent;
 - On input, the svgTextDraw from Listing 4 is called;
 - The dimensions and position of the `<textarea>` are recalculated.

The algorithm is implemented in the textareaCreate function. Function code in [a separate file on GitHub](https://github.com/AlexeyBoiko/DgrmJS/blob/main/src/diagram-extensions/infrastructure/svg-textarea.js).

An editor can be attached to any `<text>` element:
```js
const textEditor = textareaCreate(
    // {SVGTextElement}
    textEl,
    // text params
    { lineHeight: 20, verticalMiddle: 10 },
    // init value
    'init text',
    // onchange
    val => {...},
    // onblur
    val => {...});
…
// delete textarea
textEditor.remove();
```
_Listing 5. Creating a text editor for `<text>`_

## Other articles about dgrm.net
 - [JavaScript SVG diagram editor 3.9 KB (open source library)](https://dev.to/alexboyko/javascript-svg-diagram-editor-39-kb-open-source-library-2eh)
 - [JavaScript diagram editor that renders diagrams from PNG images (open source)](https://dev.to/alexboyko/javascript-diagram-editor-that-renders-diagrams-from-png-images-open-source-a63)
 - JavaScript text editor for SVG
 - [Flowchart editor UI](https://dev.to/alexboyko/flowchart-editor-ui-58a1)
 - [JavaScript: Zoom like in maps for SVG/HTML](https://dev.to/alexboyko/javascript-zoom-like-in-maps-for-svghtml-2m3b)



## How to support the project
 - Start using the flowchart editor [Dgrm.net](https://dgrm.net/).  
Tell me what you think. Comments, private messages, on [GitHub](https://github.com/AlexeyBoiko/DgrmJS).  
I read everything, I keep a list of proposals.
 - Tell your friends.
 - Give a star on [GitHub](https://github.com/AlexeyBoiko/DgrmJS).