aboutsummaryrefslogtreecommitdiff
path: root/js/components/hintable.reel/hintable.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/components/hintable.reel/hintable.js')
-rw-r--r--js/components/hintable.reel/hintable.js366
1 files changed, 366 insertions, 0 deletions
diff --git a/js/components/hintable.reel/hintable.js b/js/components/hintable.reel/hintable.js
new file mode 100644
index 00000000..5ed46b3c
--- /dev/null
+++ b/js/components/hintable.reel/hintable.js
@@ -0,0 +1,366 @@
1/* <copyright>
2 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
3 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
4 (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
5 </copyright> */
6
7/* ComputedStyleSubPanel.js */
8var Montage = require("montage").Montage,
9 Component = require("montage/ui/component").Component,
10 Editable = require("js/components/editable.reel").Editable;
11
12
13/*
14
15EDITABLE - Methods
16- startEdit
17- stopEdit
18- value
19-
20- _suggest
21- _suggestNext
22- _suggestPrev
23- _clearSuggest
24- _accept
25- _revert
26- _setCaret
27
28*/
29
30
31exports.Hintable = Montage.create(Editable, {
32 inheritsFrom : { value : Editable },
33 _matchIndex : { value : 0 },
34 matches : { value : [] },
35
36 _hint : { value : null },
37 hint : {
38 get : function() {
39 return this._hint;
40 },
41 set : function(hint) {
42 hint = hint || '';
43
44 ///// Set the hint element's text
45 this._getFirstTextNode(this.hintElement).textContent = hint;
46 ///// if hintElement was removed from the DOM, the object still
47 ///// exists, so it needs to be re-appended
48 if(this.hintElement.parentNode === null) {
49 this._element.appendChild(this.hintElement);
50 }
51
52 this._hint = hint;
53 }
54 },
55
56 _hintElement : { value : null },
57 hintElement : {
58 get : function() {
59 if(!this._hintElement) {
60 /// Remove the phantom "<BR>" element that is generated when
61 /// content editable element is empty
62 this._children(this._element, function(item) {
63 return item.nodeName === 'BR';
64 }).forEach(function(item) {
65 this._element.removeChild(item);
66 }, this);
67
68 this._hintElement = document.createElement('span');
69 this._hintElement.classList.add(this.hintClass);
70
71 this._element.appendChild(this._hintElement);
72 }
73
74 return this._hintElement;
75 },
76 set : function(el) {
77 this._hintElement = el;
78 }
79 },
80
81 _getHintDifference : {
82 value : function() {
83 if(!this.matches[this._matchIndex]) {
84 debugger;
85 }
86 return this.matches[this._matchIndex].substr(this.value.length);
87 }
88 },
89
90 hintNext : {
91 value : function(e) {
92 if(e) { e.preventDefault(); }
93 console.log('next1');
94
95 if(this._matchIndex < this.matches.length - 1) {
96 console.log('next');
97 ++this._matchIndex;
98 this.hint = this._getHintDifference();
99 }
100 }
101 },
102 hintPrev : {
103 value : function(e) {
104 if(e) { e.preventDefault(); }
105 console.log('prev1');
106 if(this._matchIndex !== 0) {
107 console.log('prev');
108 --this._matchIndex;
109 this.hint = this._getHintDifference();
110 }
111 }
112 },
113
114 accept : {
115 value: function(e, preserveCaretPosition) {
116 if(e) {
117 e.preventDefault();
118 }
119 var fullText = this._hint;
120 this.hint = null;
121 this.value += fullText;
122
123 if(!preserveCaretPosition) {
124 this.setCursor('end');
125 }
126
127 this._sendEvent('accept');
128 }
129 },
130 revert : {
131 value : function(e, forceRevert) {
132 this.hint = null;
133
134 if(this.isEditable || forceRevert) {
135 /// revert to old value
136 this.value = (this._preEditValue);
137 this._sendEvent('revert');
138 console.log('reverting');
139
140 }
141 }
142 },
143 value : {
144 get: function() {
145 return this._getFirstTextNode().textContent;
146 },
147 set: function(str) {
148 var node = this._getFirstTextNode();
149 node.textContent = str;
150 }
151 },
152
153 handleKeydown : {
154 value : function handleKeydown(e) {
155 var k = e.keyCode,
156 isCaretAtEnd, selection, text;
157
158 this._super(arguments);
159
160 if(k === 39) {
161 selection = window.getSelection();
162 text = selection.baseNode.textContent;
163 isCaretAtEnd = (selection.anchorOffset === text.length);
164 }
165
166 if(this.hint && isCaretAtEnd) {
167 ///// Advance the cursor
168 this.hint = this.hint.substr(0, 1);
169 this.accept(e);
170 this.handleInput();
171 }
172
173 this._execKeyAction(e);
174 }
175 },
176 ///// Text input has changed values
177 handleInput : {
178 value : function handleInput(e) {
179 this._super(arguments);
180
181 var val = this.value,
182 matches, hint;
183 console.log('val = "' + val + '"');
184 //// Handle auto-suggest if configured
185 if(this.hints instanceof Array) {
186
187 if(val.length > 0) { // content is not empty
188
189 this._matchIndex = 0;
190 this.matches = this.hints.filter(function(h) {
191 return h.indexOf(val) === 0;
192 }).sort();
193
194 ///// If there are no matches, or the new value doesn't match all the
195 ///// previous matches, then get new list of matches
196 if(!this.matches.length || !this._matchesAll(val)) {
197 }
198
199 if(this.matches.length) { // match(es) found
200 if(this.matches[this._matchIndex] !== val) {
201 // Suggest the matched hint, subtracting the typed-in string
202 // Only if the hint is not was the user has typed already
203 this.hint = this._getHintDifference();
204 } else {
205 this.hint = null;
206 }
207 } else { // no matches found
208 this.hint = null;
209 }
210 } else { // no suggestion for empty string
211 this.hint = null;
212 }
213
214 }
215 }
216 },
217 handleBackspace : {
218 value : function(e) {
219 this.matches.length = 0;
220 }
221 },
222 _matchesAll : {
223 value : function(value) {
224 return this.matches.every(function(match) {
225 return match.indexOf(value) === 0;
226 }, this);
227 }
228 },
229 _execKeyAction : {
230 value : function(e) {
231 var key = e.keyCode,
232 keys = this.keyActions;
233
234 if(this.hint) {
235 if( keys.hint.revert.indexOf(key) !== -1 ) { this.revert(e); }
236 if( keys.hint.accept.indexOf(key) !== -1 ) { this.accept(e); }