UNPKG

5.64 kBJavaScriptView Raw
1"use strict";
2/*
3* Copyright (C) 1998-2021 by Northwoods Software Corporation. All Rights Reserved.
4*/
5
6// This is the definitions of the predefined text editor used by TextEditingTool
7// when you set or bind TextBlock.editable to true.
8// You do not need to load this file in order to use in-place text editing.
9
10// HTML + JavaScript text editor menu, made with HTMLInfo
11// This is a re-implementation of the default text editor
12// This file exposes one instance of HTMLInfo, window.TextEditor
13// See also TextEditor.html
14(function(window) {
15 var textarea = document.createElement('textarea');
16 textarea.id = "myTextArea";
17
18 textarea.addEventListener('input', function(e) {
19 var tool = TextEditor.tool;
20 if (tool.textBlock === null) return;
21 var tempText = tool.measureTemporaryTextBlock(this.value);
22 var scale = this.textScale;
23 this.style.width = 20 + tempText.measuredBounds.width * scale + 'px';
24 this.rows = tempText.lineCount;
25 }, false);
26
27 textarea.addEventListener('keydown', function(e) {
28 var tool = TextEditor.tool;
29 if (tool.textBlock === null) return;
30 var key = e.key;
31 if (key === "Enter") {
32 if (tool.textBlock.isMultiline === false) e.preventDefault();
33 tool.acceptText(go.TextEditingTool.Enter);
34 return;
35 } else if (key === "Tab") {
36 tool.acceptText(go.TextEditingTool.Tab);
37 e.preventDefault();
38 return;
39 } else if (key === "Escape") {
40 tool.doCancel();
41 if (tool.diagram !== null) tool.diagram.doFocus();
42 }
43 }, false);
44
45 // handle focus:
46 textarea.addEventListener('focus', function(e) {
47 var tool = TextEditor.tool;
48 if (!tool || tool.currentTextEditor === null) return;
49
50 if (tool.state === go.TextEditingTool.StateActive) {
51 tool.state = go.TextEditingTool.StateEditing;
52 }
53
54 if (tool.selectsTextOnActivate) {
55 textarea.select();
56 textarea.setSelectionRange(0, 9999);
57 }
58 }, false);
59
60 // Disallow blur.
61 // If the textEditingTool blurs and the text is not valid,
62 // we do not want focus taken off the element just because a user clicked elsewhere.
63 textarea.addEventListener('blur', function(e) {
64 var tool = TextEditor.tool;
65 if (!tool || tool.currentTextEditor === null || tool.state === go.TextEditingTool.StateNone) return;
66
67 textarea.focus();
68
69 if (tool.selectsTextOnActivate) {
70 textarea.select();
71 textarea.setSelectionRange(0, 9999);
72 }
73 }, false);
74
75
76 var TextEditor = new go.HTMLInfo();
77
78 TextEditor.valueFunction = function() { return textarea.value; }
79
80 TextEditor.mainElement = textarea; // to reference it more easily
81
82 TextEditor.tool = null; // Initialize
83
84 // used to be in doActivate
85 TextEditor.show = function(textBlock, diagram, tool) {
86 if (!(textBlock instanceof go.TextBlock)) return;
87 if (TextEditor.tool !== null) return; // Only one at a time.
88
89 TextEditor.tool = tool; // remember the TextEditingTool for use by listeners
90
91 // This is called during validation, if validation failed:
92 if (tool.state === go.TextEditingTool.StateInvalid) {
93 textarea.style.border = '3px solid red';
94 textarea.focus();
95 return;
96 }
97
98 // This part is called during initalization:
99
100 var loc = textBlock.getDocumentPoint(go.Spot.Center);
101 var pos = diagram.position;
102 var sc = diagram.scale;
103 var textscale = textBlock.getDocumentScale() * sc;
104 if (textscale < tool.minimumEditorScale) textscale = tool.minimumEditorScale;
105 // Add slightly more width/height to stop scrollbars and line wrapping on some browsers
106 // +6 is firefox minimum, otherwise lines will be wrapped improperly
107 var textwidth = (textBlock.naturalBounds.width * textscale) + 6;
108 var textheight = (textBlock.naturalBounds.height * textscale) + 2;
109 var left = (loc.x - pos.x) * sc;
110 var top = (loc.y - pos.y) * sc;
111
112 textarea.value = textBlock.text;
113 // the only way you can mix font and fontSize is if the font inherits and the fontSize overrides
114 // in the future maybe have textarea contained in its own div
115 diagram.div.style['font'] = textBlock.font;
116
117 var paddingsize = 1;
118 textarea.style['position'] = 'absolute';
119 textarea.style['zIndex'] = '100';
120 textarea.style['font'] = 'inherit';
121 textarea.style['fontSize'] = (textscale * 100) + '%';
122 textarea.style['lineHeight'] = 'normal';
123 textarea.style['width'] = (textwidth) + 'px';
124 textarea.style['left'] = ((left - (textwidth / 2) | 0) - paddingsize) + 'px';
125 textarea.style['top'] = ((top - (textheight / 2) | 0) - paddingsize) + 'px';
126 textarea.style['textAlign'] = textBlock.textAlign;
127 textarea.style['margin'] = '0';
128 textarea.style['padding'] = paddingsize + 'px';
129 textarea.style['border'] = '0';
130 textarea.style['outline'] = 'none';
131 textarea.style['whiteSpace'] = 'pre-wrap';
132 textarea.style['overflow'] = 'hidden'; // for proper IE wrap
133 textarea.rows = textBlock.lineCount;
134 textarea.textScale = textscale; // attach a value to the textarea, for convenience
135 textarea.className = 'goTXarea';
136
137 // Show:
138 diagram.div.appendChild(textarea);
139
140 // After adding, focus:
141 textarea.focus();
142 if (tool.selectsTextOnActivate) {
143 textarea.select();
144 textarea.setSelectionRange(0, 9999);
145 }
146 };
147
148 TextEditor.hide = function(diagram, tool) {
149 diagram.div.removeChild(textarea);
150 TextEditor.tool = null; // forget reference to TextEditingTool
151 }
152
153 window.TextEditor = TextEditor;
154})(window);