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 |
|
34 |
|
35 |
|
36 | function Button( options ) {
|
37 |
|
38 | options = ! options ? {} : options.internal ? options : Object.create( options ) ;
|
39 | options.internal = true ;
|
40 |
|
41 | this.blurLeftPadding = options.blurLeftPadding || options.leftPadding || '' ;
|
42 | this.blurRightPadding = options.blurRightPadding || options.rightPadding || '' ;
|
43 | this.focusLeftPadding = options.focusLeftPadding || options.leftPadding || '' ;
|
44 | this.focusRightPadding = options.focusRightPadding || options.rightPadding || '' ;
|
45 | this.disabledLeftPadding = options.disabledLeftPadding || options.leftPadding || '' ;
|
46 | this.disabledRightPadding = options.disabledRightPadding || options.rightPadding || '' ;
|
47 | this.submittedLeftPadding = options.submittedLeftPadding || options.leftPadding || '' ;
|
48 | this.submittedRightPadding = options.submittedRightPadding || options.rightPadding || '' ;
|
49 |
|
50 |
|
51 | this.turnedOnFocusLeftPadding = options.turnedOnFocusLeftPadding || options.turnedOnLeftPadding || options.leftPadding || '' ;
|
52 | this.turnedOnFocusRightPadding = options.turnedOnFocusRightPadding || options.turnedOnRightPadding || options.rightPadding || '' ;
|
53 | this.turnedOffFocusLeftPadding = options.turnedOffFocusLeftPadding || options.turnedOffLeftPadding || options.leftPadding || '' ;
|
54 | this.turnedOffFocusRightPadding = options.turnedOffFocusRightPadding || options.turnedOffRightPadding || options.rightPadding || '' ;
|
55 | this.turnedOnBlurLeftPadding = options.turnedOnBlurLeftPadding || options.turnedOnLeftPadding || options.leftPadding || '' ;
|
56 | this.turnedOnBlurRightPadding = options.turnedOnBlurRightPadding || options.turnedOnRightPadding || options.rightPadding || '' ;
|
57 | this.turnedOffBlurLeftPadding = options.turnedOffBlurLeftPadding || options.turnedOffLeftPadding || options.leftPadding || '' ;
|
58 | this.turnedOffBlurRightPadding = options.turnedOffBlurRightPadding || options.turnedOffRightPadding || options.rightPadding || '' ;
|
59 |
|
60 | this.paddingHasMarkup = !! options.paddingHasMarkup ;
|
61 |
|
62 |
|
63 | this.internalRole = options.internalRole || null ;
|
64 |
|
65 | if ( ! Array.isArray( options.content ) ) {
|
66 | options.content = [ options.content || '' ] ;
|
67 | }
|
68 |
|
69 | options.width =
|
70 | Math.max(
|
71 | Element.computeContentWidth( this.blurLeftPadding , this.paddingHasMarkup ) ,
|
72 | Element.computeContentWidth( this.focusLeftPadding , this.paddingHasMarkup ) ,
|
73 | Element.computeContentWidth( this.disabledLeftPadding , this.paddingHasMarkup ) ,
|
74 | Element.computeContentWidth( this.submittedLeftPadding , this.paddingHasMarkup ) ,
|
75 | Element.computeContentWidth( this.turnedOnFocusLeftPadding , this.paddingHasMarkup ) ,
|
76 | Element.computeContentWidth( this.turnedOffFocusLeftPadding , this.paddingHasMarkup ) ,
|
77 | Element.computeContentWidth( this.turnedOnBlurLeftPadding , this.paddingHasMarkup ) ,
|
78 | Element.computeContentWidth( this.turnedOffBlurLeftPadding , this.paddingHasMarkup )
|
79 | ) + Math.max(
|
80 | Element.computeContentWidth( this.blurRightPadding , this.paddingHasMarkup ) ,
|
81 | Element.computeContentWidth( this.focusRightPadding , this.paddingHasMarkup ) ,
|
82 | Element.computeContentWidth( this.disabledRightPadding , this.paddingHasMarkup ) ,
|
83 | Element.computeContentWidth( this.submittedRightPadding , this.paddingHasMarkup ) ,
|
84 | Element.computeContentWidth( this.turnedOnFocusRightPadding , this.paddingHasMarkup ) ,
|
85 | Element.computeContentWidth( this.turnedOffFocusRightPadding , this.paddingHasMarkup ) ,
|
86 | Element.computeContentWidth( this.turnedOnBlurRightPadding , this.paddingHasMarkup ) ,
|
87 | Element.computeContentWidth( this.turnedOffBlurRightPadding , this.paddingHasMarkup )
|
88 | ) +
|
89 | Element.computeContentWidth( options.content , options.contentHasMarkup ) || 1 ;
|
90 |
|
91 | options.height = options.content.length ;
|
92 |
|
93 | Text.call( this , options ) ;
|
94 |
|
95 | this.blurAttr = options.blurAttr || { bgColor: 'brightBlack' } ;
|
96 | this.focusAttr = options.focusAttr || { bgColor: 'blue' } ;
|
97 | this.disabledAttr = options.disabledAttr || { bgColor: 'black' , color: 'brightBlack' } ;
|
98 | this.submittedAttr = options.submittedAttr || { bgColor: 'brightBlue' } ;
|
99 | this.turnedOnBlurAttr = options.turnedOnBlurAttr || { bgColor: 'cyan' } ;
|
100 | this.turnedOnFocusAttr = options.turnedOnFocusAttr || { bgColor: 'brightCyan' , bold: true } ;
|
101 | this.turnedOffBlurAttr = options.turnedOffBlurAttr || { bgColor: 'gray' , dim: true } ;
|
102 | this.turnedOffFocusAttr = options.turnedOffFocusAttr || { bgColor: 'white' , color: 'black' , bold: true } ;
|
103 |
|
104 | this.disabled = !! options.disabled ;
|
105 | this.submitted = !! options.submitted ;
|
106 |
|
107 | this.attr = null ;
|
108 | this.leftPadding = null ;
|
109 | this.rightPadding = null ;
|
110 | this.updateStatus() ;
|
111 |
|
112 | this.onKey = this.onKey.bind( this ) ;
|
113 | this.onShortcut = this.onShortcut.bind( this ) ;
|
114 | this.onFocus = this.onFocus.bind( this ) ;
|
115 | this.onHover = this.onHover.bind( this ) ;
|
116 | this.onClick = this.onClick.bind( this ) ;
|
117 |
|
118 | if ( options.keyBindings ) { this.keyBindings = options.keyBindings ; }
|
119 | if ( options.actionKeyBindings ) { this.actionKeyBindings = options.actionKeyBindings ; }
|
120 |
|
121 | this.on( 'key' , this.onKey ) ;
|
122 | this.on( 'shortcut' , this.onShortcut ) ;
|
123 | this.on( 'focus' , this.onFocus ) ;
|
124 | this.on( 'click' , this.onClick ) ;
|
125 | this.on( 'hover' , this.onHover ) ;
|
126 |
|
127 | if ( this.elementType === 'Button' && ! options.noDraw ) { this.draw() ; }
|
128 | }
|
129 |
|
130 | module.exports = Button ;
|
131 |
|
132 | Button.prototype = Object.create( Text.prototype ) ;
|
133 | Button.prototype.constructor = Button ;
|
134 | Button.prototype.elementType = 'Button' ;
|
135 |
|
136 |
|
137 |
|
138 | Button.prototype.keyBindings = {
|
139 | ENTER: 'submit' ,
|
140 | KP_ENTER: 'submit' ,
|
141 | ALT_ENTER: 'submit'
|
142 | } ;
|
143 |
|
144 |
|
145 |
|
146 | Button.prototype.actionKeyBindings = {} ;
|
147 |
|
148 |
|
149 |
|
150 | Button.prototype.destroy = function( isSubDestroy , noDraw ) {
|
151 | this.off( 'key' , this.onKey ) ;
|
152 | this.off( 'shortcut' , this.onShortcut ) ;
|
153 | this.off( 'focus' , this.onFocus ) ;
|
154 | this.off( 'click' , this.onClick ) ;
|
155 | this.off( 'hover' , this.onHover ) ;
|
156 |
|
157 | Element.prototype.destroy.call( this , isSubDestroy , noDraw ) ;
|
158 | } ;
|
159 |
|
160 |
|
161 |
|
162 | Button.prototype.drawSelfCursor = function() {
|
163 |
|
164 | this.outputDst.moveTo( this.outputX , this.outputY ) ;
|
165 | this.outputDst.drawCursor() ;
|
166 | } ;
|
167 |
|
168 |
|
169 |
|
170 |
|
171 | Button.prototype.blink = function( animationCountdown = 4 ) {
|
172 | if ( animationCountdown ) {
|
173 | if ( animationCountdown % 2 ) { this.attr = this.focusAttr ; }
|
174 | else { this.attr = this.blurAttr ; }
|
175 |
|
176 | this.draw() ;
|
177 | setTimeout( () => this.blink( animationCountdown - 1 ) , 80 ) ;
|
178 | }
|
179 | else {
|
180 | this.updateStatus() ;
|
181 | this.draw() ;
|
182 | }
|
183 | } ;
|
184 |
|
185 |
|
186 |
|
187 | Button.prototype.onFocus = function( focus , type ) {
|
188 | this.hasFocus = focus ;
|
189 | this.updateStatus() ;
|
190 | this.draw() ;
|
191 | } ;
|
192 |
|
193 |
|
194 |
|
195 | Button.prototype.updateStatus = function() {
|
196 | if ( this.disabled ) {
|
197 | this.attr = this.disabledAttr ;
|
198 | this.leftPadding = this.disabledLeftPadding ;
|
199 | this.rightPadding = this.disabledRightPadding ;
|
200 | }
|
201 | else if ( this.submitted ) {
|
202 | this.attr = this.submittedAttr ;
|
203 | this.leftPadding = this.submittedLeftPadding ;
|
204 | this.rightPadding = this.submittedRightPadding ;
|
205 | }
|
206 | else if ( this.hasFocus ) {
|
207 | this.attr = this.focusAttr ;
|
208 | this.leftPadding = this.focusLeftPadding ;
|
209 | this.rightPadding = this.focusRightPadding ;
|
210 | }
|
211 | else {
|
212 | this.attr = this.blurAttr ;
|
213 | this.leftPadding = this.blurLeftPadding ;
|
214 | this.rightPadding = this.blurRightPadding ;
|
215 | }
|
216 | } ;
|
217 |
|
218 |
|
219 |
|
220 | Button.prototype.onKey = function( key , altKeys , data ) {
|
221 | switch( this.keyBindings[ key ] ) {
|
222 | case 'submit' :
|
223 | if ( this.disabled || this.submitted ) { break ; }
|
224 | this.emit( 'submit' , this.value , this.actionKeyBindings[ key ] , this ) ;
|
225 | this.blink() ;
|
226 | break ;
|
227 | default :
|
228 | return ;
|
229 | }
|
230 |
|
231 | return true ;
|
232 | } ;
|
233 |
|
234 |
|
235 |
|
236 | Button.prototype.onHover = function( data ) {
|
237 | if ( this.disabled || this.submitted ) { return ; }
|
238 | this.document.giveFocusTo( this , 'hover' ) ;
|
239 | } ;
|
240 |
|
241 |
|
242 |
|
243 | Button.prototype.onClick = function( data ) {
|
244 | if ( this.disabled || this.submitted ) { return ; }
|
245 | this.document.giveFocusTo( this , 'select' ) ;
|
246 | this.emit( 'submit' , this.value , undefined , this ) ;
|
247 | this.blink() ;
|
248 | } ;
|
249 |
|
250 |
|
251 |
|
252 | Button.prototype.onShortcut = function() {
|
253 | if ( this.disabled || this.submitted ) { return ; }
|
254 | this.document.giveFocusTo( this , 'select' ) ;
|
255 | this.emit( 'submit' , this.value , undefined , this ) ;
|
256 | this.blink() ;
|
257 | } ;
|
258 |
|