/
HintTextBox.qui
148 lines (131 loc) · 4.08 KB
/
HintTextBox.qui
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<!-- A text box that shows a "hint" as to what the user should enter. -->
<Control className="HintTextBox" generic="true">
<content>
<input ref="HintTextBox_textBox" type="text"/>
<div ref="HintTextBox_hint"/>
</content>
<style>
{
cursor: text;
display: inline-block;
position: relative;
}
.HintTextBox_textBox {
-moz-box-sizing: border-box;
box-sizing: border-box;
font-size: 1em;
width: 100%;
}
.HintTextBox_hint {
bottom: 0;
left: 4px;
height: 1.25em;
margin: auto 0;
position: absolute;
overflow: hidden;
right: 4px;
top: 0;
}
/* Generic appearance */
.HintTextBox.generic .HintTextBox_hint {
color: #aaa;
}
</style>
<script>
HintTextBox.prototype.extend({
/*
* The content of the text box.
*/
content: Control.chain( "$HintTextBox_textBox", "content", function() {
this._showHintIfEmpty();
}),
/*
* The "hint" shown within the text box that suggests what the user should
* type there. This hint is hidden if: the text box has content, the
* text box has just acquired the keyboard focus, or if the user clicks in
* the text box.
*/
hint: Control.chain( "$HintTextBox_hint", "content" ),
initialize: function() {
var self = this;
this.on({
"click": function() { self._hideHint(); },
"focus": function() {
if ( !self._isTextBoxFocused() )
{
self.$HintTextBox_textBox().focus();
}
}
});
this.$HintTextBox_textBox().on({
blur: function() {
self
._isTextBoxFocused( false )
._showHintIfEmpty();
},
focus: function() { self._isTextBoxFocused( true ); },
keydown: function( event ) { self._handleKeydown( event ); },
keyup: function() { self._showHintIfEmpty(); }
});
this.$HintTextBox_hint().click( function() {
self._hideHint();
});
},
_isTextBoxFocused: Control.property( null, false ),
/*
* The keydown event comes before the browser has processed it, so we can't
* tell at this point for sure what the final text is. However, we can
* speculate as to whether the result of the key will add or remove text.
* Most keys will add a character to the text box, in which case we'll end
* up removing the hint; rather than waiting for keyup to check whether the
* text is non-empty, we'll hide the hint now. In special cases, we defer
* hiding the hint until the keyup event, when we can check the final text
* that includes the result of the key.
*/
_handleKeydown: function( event ) {
var keysOfUnknownEffect = [
8, // Backspace
9, // Tab
16, // Shift
17, // Ctrl
18, // Alt
19, // Pause/Break
20, // Caps Lock
27, // Esc
33, // Page Up
34, // Page Down
35, // End
36, // Home
37, // Left
38, // Up
39, // Right
40, // Down
45, // Insert
46, // Delete
91, // Windows
93, // Context menu
144, // Num lock
145, // Scroll lock
182, // Computer
183, // Calculator
];
if ( $.inArray( event.which, keysOfUnknownEffect ) < 0 ) {
// Probably a text key. Preemptively hide the hint.
this.$HintTextBox_hint().hide();
}
},
_hideHint: function() {
this.$HintTextBox_hint().hide();
this.$HintTextBox_textBox().focus();
},
/*
* This routine is a more careful check to see whether we should show the
* hint or not. We can call this on blur or keyup (when, unlike keydown,
* the final state of the text is known).
*/
_showHintIfEmpty: function() {
this.$HintTextBox_hint().toggle( this.content().length === 0 );
}
});
</script>
</Control>