1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | "use strict" ;
|
28 |
|
29 |
|
30 |
|
31 | const Element = require( './Element.js' ) ;
|
32 | const Text = require( './Text.js' ) ;
|
33 | const EditableTextBox = require( './EditableTextBox.js' ) ;
|
34 | const SelectList = require( './SelectList.js' ) ;
|
35 | const SelectListMulti = require( './SelectListMulti.js' ) ;
|
36 |
|
37 | const string = require( 'string-kit' ) ;
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | function LabeledInput( options ) {
|
44 |
|
45 | options = ! options ? {} : options.internal ? options : Object.create( options ) ;
|
46 | options.internal = true ;
|
47 |
|
48 | Element.call( this , options ) ;
|
49 |
|
50 |
|
51 | this.hiddenContent = options.hiddenContent ;
|
52 |
|
53 |
|
54 | this.interceptTempZIndex = true ;
|
55 |
|
56 | this.labelFocusAttr = options.labelFocusAttr || { bold: true } ;
|
57 | this.labelBlurAttr = options.labelBlurAttr || { dim: true } ;
|
58 |
|
59 | this.buttonBlurAttr = options.buttonBlurAttr || { bgColor: 'cyan' , color: 'white' , bold: true } ;
|
60 | this.buttonFocusAttr = options.buttonFocusAttr || { bgColor: 'brightCyan' , color: 'black' , bold: true } ;
|
61 | this.buttonDisabledAttr = options.buttonDisabledAttr || { bgColor: 'cyan' , color: 'gray' , bold: true } ;
|
62 | this.buttonSubmittedAttr = options.buttonSubmittedAttr || { bgColor: 'brightCyan' , color: 'brightWhite' , bold: true } ;
|
63 | this.turnedOnBlurAttr = options.turnedOnBlurAttr || { bgColor: 'cyan' } ;
|
64 | this.turnedOnFocusAttr = options.turnedOnFocusAttr || { bgColor: 'brightCyan' , bold: true } ;
|
65 | this.turnedOffBlurAttr = options.turnedOffBlurAttr || { bgColor: 'gray' , dim: true } ;
|
66 | this.turnedOffFocusAttr = options.turnedOffFocusAttr || { bgColor: 'white' , color: 'black' , bold: true } ;
|
67 |
|
68 |
|
69 | this.textAttr = options.textAttr || { bgColor: 'blue' } ;
|
70 | this.voidAttr = options.voidAttr || options.emptyAttr || { bgColor: 'blue' } ;
|
71 |
|
72 | if ( options.keyBindings ) { this.keyBindings = options.keyBindings ; }
|
73 |
|
74 | if ( this.label ) {
|
75 | this.labelText = new Text( {
|
76 | internal: true ,
|
77 | parent: this ,
|
78 | content: this.label ,
|
79 | x: this.outputX ,
|
80 | y: this.outputY ,
|
81 | height: 1 ,
|
82 | attr: this.labelBlurAttr ,
|
83 | leftPadding: this.labelBlurLeftPadding ,
|
84 | rightPadding: this.labelBlurRightPadding ,
|
85 | noDraw: true
|
86 | } ) ;
|
87 | }
|
88 |
|
89 | this.inputType = options.type || 'text' ;
|
90 |
|
91 | this.onKey = this.onKey.bind( this ) ;
|
92 | this.onFocus = this.onFocus.bind( this ) ;
|
93 | this.onClick = this.onClick.bind( this ) ;
|
94 | this.onInputSubmit = this.onInputSubmit.bind( this ) ;
|
95 |
|
96 | this.initInput( options ) ;
|
97 | this.updateStatus() ;
|
98 |
|
99 | this.on( 'key' , this.onKey ) ;
|
100 | this.on( 'focus' , this.onFocus ) ;
|
101 | this.on( 'click' , this.onClick ) ;
|
102 |
|
103 |
|
104 | if ( this.elementType === 'LabeledInput' && ! options.noDraw ) { this.draw() ; }
|
105 | }
|
106 |
|
107 | module.exports = LabeledInput ;
|
108 |
|
109 | LabeledInput.prototype = Object.create( Element.prototype ) ;
|
110 | LabeledInput.prototype.constructor = LabeledInput ;
|
111 | LabeledInput.prototype.elementType = 'LabeledInput' ;
|
112 |
|
113 |
|
114 |
|
115 | LabeledInput.prototype.noChildFocus = true ;
|
116 | LabeledInput.prototype.propagateZ = true ;
|
117 |
|
118 |
|
119 |
|
120 | LabeledInput.prototype.destroy = function( isSubDestroy ) {
|
121 | this.off( 'key' , this.onKey ) ;
|
122 | this.off( 'focus' , this.onFocus ) ;
|
123 | this.off( 'click' , this.onClick ) ;
|
124 | if ( this.input ) { this.off( 'submit' , this.onInputSubmit ) ; }
|
125 |
|
126 | Element.prototype.destroy.call( this , isSubDestroy ) ;
|
127 | } ;
|
128 |
|
129 |
|
130 |
|
131 | LabeledInput.prototype.keyBindings = {
|
132 | ENTER: 'submit' ,
|
133 | KP_ENTER: 'submit' ,
|
134 | ALT_ENTER: 'submit'
|
135 |
|
136 | } ;
|
137 |
|
138 |
|
139 |
|
140 | LabeledInput.prototype.editableTextBoxKeyBindings = {
|
141 | BACKSPACE: 'backDelete' ,
|
142 | DELETE: 'delete' ,
|
143 | LEFT: 'backward' ,
|
144 | RIGHT: 'forward' ,
|
145 | CTRL_LEFT: 'startOfWord' ,
|
146 | CTRL_RIGHT: 'endOfWord' ,
|
147 | HOME: 'startOfLine' ,
|
148 | END: 'endOfLine' ,
|
149 | CTRL_O: 'copyClipboard' ,
|
150 | CTRL_P: 'pasteClipboard'
|
151 | } ;
|
152 |
|
153 |
|
154 |
|
155 | LabeledInput.prototype.multiLineEditableTextBoxKeyBindings = Object.assign( {} , LabeledInput.prototype.editableTextBoxKeyBindings , {
|
156 | ENTER: 'newLine' ,
|
157 | KP_ENTER: 'newLine' ,
|
158 | UP: 'up' ,
|
159 | DOWN: 'down' ,
|
160 | PAGE_UP: 'scrollUp' ,
|
161 | PAGE_DOWN: 'scrollDown' ,
|
162 | CTRL_O: 'copyClipboard' ,
|
163 | CTRL_P: 'pasteClipboard'
|
164 | } ) ;
|
165 |
|
166 |
|
167 |
|
168 | LabeledInput.prototype.selectListKeyBindings = {
|
169 | UP: 'previous' ,
|
170 | DOWN: 'next' ,
|
171 | ENTER: 'submit' ,
|
172 | KP_ENTER: 'submit'
|
173 | } ;
|
174 |
|
175 |
|
176 |
|
177 | LabeledInput.prototype.selectListMultiKeyBindings = {
|
178 | UP: 'previous' ,
|
179 | DOWN: 'next' ,
|
180 | ENTER: 'submit' ,
|
181 | KP_ENTER: 'submit'
|
182 | } ;
|
183 |
|
184 |
|
185 |
|
186 | LabeledInput.prototype.initInput = function( options ) {
|
187 | switch ( this.inputType ) {
|
188 | case 'text' :
|
189 | this.initTextInput( options ) ;
|
190 | break ;
|
191 | case 'select' :
|
192 | this.initSelectInput( options ) ;
|
193 | break ;
|
194 | case 'selectMulti' :
|
195 | this.initSelectMultiInput( options ) ;
|
196 | break ;
|
197 | default :
|
198 | throw new Error( 'Unknown input type: ' + this.inputType ) ;
|
199 | }
|
200 | } ;
|
201 |
|
202 |
|
203 |
|
204 | LabeledInput.prototype.initTextInput = function( options ) {
|
205 | if ( options.inputKeyBindings ) { this.inputKeyBindings = options.inputKeyBindings ; }
|
206 | else if ( options.allowNewLine ) { this.inputKeyBindings = this.multiLineEditableTextBoxKeyBindings ; }
|
207 | else { this.inputKeyBindings = this.editableTextBoxKeyBindings ; }
|
208 |
|
209 | this.input = new EditableTextBox( {
|
210 | internal: true ,
|
211 | parent: this ,
|
212 | content: options.content ,
|
213 | value: options.value ,
|
214 | x: this.outputX + ( this.labelText ? this.labelText.outputWidth : 0 ) ,
|
215 | y: this.outputY ,
|
216 | width: this.outputWidth - ( this.labelText ? this.labelText.outputWidth : 0 ) ,
|
217 | height: this.outputHeight ,
|
218 | lineWrap: !! options.lineWrap ,
|
219 | wordWrap: !! options.wordWrap ,
|
220 | scrollable: !! options.scrollable ,
|
221 | vScrollBar: !! options.vScrollBar ,
|
222 | hScrollBar: !! options.hScrollBar ,
|
223 | hiddenContent: this.hiddenContent ,
|
224 | textAttr: this.textAttr ,
|
225 | voidAttr: this.voidAttr ,
|
226 | keyBindings: this.inputKeyBindings ,
|
227 | noDraw: true
|
228 | } ) ;
|
229 | } ;
|
230 |
|
231 |
|
232 |
|
233 | LabeledInput.prototype.initSelectInput = function( options ) {
|
234 | if ( options.inputKeyBindings ) { this.inputKeyBindings = options.inputKeyBindings ; }
|
235 | else { this.inputKeyBindings = this.selectListKeyBindings ; }
|
236 |
|
237 | this.input = new SelectList( {
|
238 | internal: true ,
|
239 | parent: this ,
|
240 | content: options.content ,
|
241 | value: options.value ,
|
242 | x: this.outputX + ( this.labelText ? this.labelText.outputWidth : 0 ) ,
|
243 | y: this.outputY ,
|
244 | width: this.outputWidth - ( this.labelText ? this.labelText.outputWidth : 0 ) ,
|
245 | items: options.items ,
|
246 | buttonBlurAttr: this.buttonBlurAttr ,
|
247 | buttonFocusAttr: this.buttonFocusAttr ,
|
248 | buttonDisabledAttr: this.buttonDisabledAttr ,
|
249 | buttonSubmittedAttr: this.buttonSubmittedAttr ,
|
250 | keyBindings: this.inputKeyBindings ,
|
251 | noDraw: true
|
252 | } ) ;
|
253 |
|
254 | this.input.on( 'submit' , this.onInputSubmit ) ;
|
255 | } ;
|
256 |
|
257 |
|
258 |
|
259 | LabeledInput.prototype.initSelectMultiInput = function( options ) {
|
260 | if ( options.inputKeyBindings ) { this.inputKeyBindings = options.inputKeyBindings ; }
|
261 | else { this.inputKeyBindings = this.selectListMultiKeyBindings ; }
|
262 |
|
263 | this.input = new SelectListMulti( {
|
264 | internal: true ,
|
265 | parent: this ,
|
266 | content: options.content ,
|
267 | value: options.value ,
|
268 | x: this.outputX + ( this.labelText ? this.labelText.outputWidth : 0 ) ,
|
269 | y: this.outputY ,
|
270 | width: this.outputWidth - ( this.labelText ? this.labelText.outputWidth : 0 ) ,
|
271 | items: options.items ,
|
272 | buttonBlurAttr: this.buttonBlurAttr ,
|
273 | buttonFocusAttr: this.buttonFocusAttr ,
|
274 | buttonDisabledAttr: this.buttonDisabledAttr ,
|
275 | buttonSubmittedAttr: this.buttonSubmittedAttr ,
|
276 | turnedOnBlurAttr: this.turnedOnBlurAttr ,
|
277 | turnedOnFocusAttr: this.turnedOnFocusAttr ,
|
278 | turnedOffBlurAttr: this.turnedOffBlurAttr ,
|
279 | turnedOffFocusAttr: this.turnedOffFocusAttr ,
|
280 | keyBindings: this.inputKeyBindings ,
|
281 | noDraw: true
|
282 | } ) ;
|
283 |
|
284 | this.input.on( 'submit' , this.onInputSubmit ) ;
|
285 | } ;
|
286 |
|
287 |
|
288 |
|
289 | LabeledInput.prototype.updateStatus = function() {
|
290 | |
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 | if ( this.hasFocus ) {
|
303 | if ( this.labelText ) {
|
304 | this.labelText.attr = this.labelFocusAttr ;
|
305 | this.labelText.leftPadding = this.labelFocusLeftPadding ;
|
306 | this.labelText.rightPadding = this.labelFocusRightPadding ;
|
307 | }
|
308 | }
|
309 | else if ( this.labelText ) {
|
310 | this.labelText.attr = this.labelBlurAttr ;
|
311 | this.labelText.leftPadding = this.labelBlurLeftPadding ;
|
312 | this.labelText.rightPadding = this.labelBlurRightPadding ;
|
313 | }
|
314 | } ;
|
315 |
|
316 |
|
317 |
|
318 |
|
319 | LabeledInput.prototype.getValue = function() { return this.input.getValue() ; } ;
|
320 | LabeledInput.prototype.setValue = function( value , dontDraw ) { return this.input.setValue( value , dontDraw ) ; } ;
|
321 | LabeledInput.prototype.getContent = function() { return this.input.getContent() ; } ;
|
322 | LabeledInput.prototype.setContent = function( content , hasMarkup , dontDraw ) { return this.input.setContent( content , hasMarkup , dontDraw ) ; } ;
|
323 |
|
324 |
|
325 |
|
326 | LabeledInput.prototype.drawSelfCursor = function() {
|
327 | if ( this.input.drawSelfCursor ) { this.input.drawSelfCursor() ; }
|
328 | } ;
|
329 |
|
330 |
|
331 |
|
332 | LabeledInput.prototype.onKey = function( key , altKeys , data ) {
|
333 |
|
334 | if ( this.input.emit( 'key' , key , altKeys , data ).interrupt ) { return true ; }
|
335 |
|
336 | switch( this.keyBindings[ key ] ) {
|
337 | case 'submit' :
|
338 | this.emit( 'submit' , this.getValue() , undefined , this ) ;
|
339 | break ;
|
340 |
|
341 | default :
|
342 | return ;
|
343 | }
|
344 |
|
345 | return true ;
|
346 | } ;
|
347 |
|
348 |
|
349 |
|
350 | LabeledInput.prototype.onInputSubmit = function( data ) {
|
351 | this.emit( 'submit' , this.getValue() , undefined , this ) ;
|
352 | } ;
|
353 |
|
354 |
|
355 |
|
356 | LabeledInput.prototype.onFocus = function( focus , type ) {
|
357 | this.hasFocus = focus ;
|
358 | this.updateStatus() ;
|
359 | this.draw() ;
|
360 | } ;
|
361 |
|
362 |
|
363 |
|
364 | LabeledInput.prototype.onClick = function( data ) {
|
365 | this.document.giveFocusTo( this , 'select' ) ;
|
366 | } ;
|
367 |
|