diff options
Diffstat (limited to 'js/components/editable.reel')
-rw-r--r-- | js/components/editable.reel/editable.js | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/js/components/editable.reel/editable.js b/js/components/editable.reel/editable.js new file mode 100644 index 00000000..9c8946c4 --- /dev/null +++ b/js/components/editable.reel/editable.js | |||
@@ -0,0 +1,256 @@ | |||
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 */ | ||
8 | var Montage = require("montage").Montage, | ||
9 | Component = require("montage/ui/component").Component; | ||
10 | |||
11 | |||
12 | /* | ||
13 | |||
14 | EDITABLE - Methods | ||
15 | - startEdit | ||
16 | - stopEdit | ||
17 | - value | ||
18 | - | ||
19 | - _suggest | ||
20 | - _suggestNext | ||
21 | - _suggestPrev | ||
22 | - _clearSuggest | ||
23 | - _accept | ||
24 | - _revert | ||
25 | - _setCaret | ||
26 | |||
27 | */ | ||
28 | |||
29 | |||
30 | exports.Editable = Montage.create(Component, { | ||
31 | hasTemplate: { value: false }, | ||
32 | |||
33 | _element : { value : null }, | ||
34 | element : { | ||
35 | get : function() { | ||
36 | return this._element; | ||
37 | }, | ||
38 | set : function(el) { | ||
39 | this._element = el; | ||
40 | this._element.addEventListener('keydown', this, false); | ||
41 | this._element.addEventListener('input', this, false); | ||
42 | |||
43 | if(this.startOnEvent) { | ||
44 | this._element.addEventListener(this.startOnEvent, this, false); | ||
45 | } | ||
46 | |||
47 | } | ||
48 | }, | ||
49 | _readOnly : { | ||
50 | value: false | ||
51 | }, | ||
52 | readOnly : { | ||
53 | get : function() { return this._readOnly; }, | ||
54 | set : function(makeReadOnly) { | ||
55 | var action = makeReadOnly ? 'add' : 'remove'; | ||
56 | |||
57 | this._element.classList[action](this.readOnlyClass); | ||
58 | |||
59 | if(this.isEditable) { | ||
60 | this.stop(); | ||
61 | } | ||
62 | this._readOnly = makeReadOnly; | ||
63 | } | ||
64 | }, | ||
65 | _isEditable : { | ||
66 | value : false | ||
67 | }, | ||
68 | isEditable : { | ||
69 | get : function() { | ||
70 | return this._isEditable; | ||
71 | }, | ||
72 | set: function(makeEditable) { | ||
73 | if(this._readOnly && makeEditable) { return false; } | ||
74 | this._isEditable = makeEditable; | ||
75 | } | ||
76 | }, | ||
77 | _isDirty : { | ||
78 | value: false | ||
79 | }, | ||
80 | isDirty : { | ||
81 | get : function() { | ||
82 | return this._isDirty; | ||
83 | }, | ||
84 | set : function(setDirty) { | ||
85 | if(setDirty) { | ||
86 | this._isDirty = true; | ||
87 | this._sendEvent('dirty'); | ||
88 | } else { | ||
89 | this._isDirty = false; | ||
90 | } | ||
91 | } | ||
92 | }, | ||
93 | value : { | ||
94 | get: function() { | ||
95 | return this._element.textContent; | ||
96 | }, | ||
97 | set: function(str) { | ||
98 | this._element.textContent = str; | ||
99 | } | ||
100 | }, | ||
101 | |||
102 | ///// Pre Edit Value | ||
103 | ///// Value stored when editing starts | ||
104 | ///// Useful for reverting to previous value | ||
105 | |||
106 | _preEditValue : { | ||
107 | value : null | ||
108 | }, | ||
109 | start : { | ||
110 | value: function() { | ||
111 | if(!this._readOnly) { | ||
112 | this._isEditable = this._element.contentEditable = true; | ||
113 | this._element.classList.add(this.editingClass); | ||
114 | |||
115 | ///// Save the preEditValue | ||
116 | this._preEditValue = this.value; | ||
117 | |||
118 | if(this.selectOnStart) { | ||
119 | this.selectAll(); | ||
120 | } | ||
121 | |||
122 | if(this.stopOnBlur) { | ||
123 | console.log('adding mousedown event listener'); | ||
124 | ///// Simulate blur on editable node by listening to the doc | ||
125 | document.addEventListener('mouseup', this, false); | ||
126 | } | ||
127 | |||
128 | this._sendEvent('start'); | ||
129 | } | ||
130 | |||
131 | } | ||
132 | }, | ||
133 | stop : { | ||
134 | value: function() { | ||
135 | this._isEditable = this._element.contentEditable = false; | ||
136 | this._element.classList.remove(this.editingClass); | ||
137 | |||
138 | this._sendEvent('stop'); | ||
139 | |||
140 | ///// if value is different than pre-edit val, call onchange method | ||
141 | if(this._preEditValue !== this.value) { | ||
142 | this._sendEvent('change'); | ||
143 | } | ||
144 | } | ||
145 | }, | ||
146 | selectAll : { | ||
147 | value : function() { | ||
148 | var range = document.createRange(), | ||
149 | sel = window.getSelection(); | ||
150 | |||
151 | sel.removeAllRanges(); | ||
152 | range.selectNodeContents(this._element); | ||
153 | sel.addRange(range); | ||
154 | } | ||
155 | }, | ||
156 | setCursor : { | ||
157 | value : function(position) { | ||
158 | var index = position, | ||
159 | range, node, sel; | ||
160 | |||
161 | ///// argument can be "end" or an index | ||
162 | if(typeof position === 'string' && position === 'end') { | ||
163 | index = this.value.length; | ||
164 | } | ||
165 | |||
166 | sel = window.getSelection(); | ||
167 | sel.removeAllRanges(); | ||
168 | //debugger; | ||
169 | node = this._getFirstTextNode(); | ||
170 | range = document.createRange(); | ||
171 | range.setStart(node, index); | ||
172 | range.setEnd(node, index); | ||
173 | sel.addRange(range); | ||
174 | } | ||
175 | }, | ||
176 | blur : { | ||
177 | value : function() { | ||
178 | if(this._hint) { | ||
179 | this.accept(); | ||
180 | } | ||
181 | this.stop(); | ||
182 | document.removeEventListener('mouseup', this, false); | ||
183 | this._sendEvent('blur'); | ||
184 | } | ||
185 | }, | ||
186 | |||
187 | /* -------------------- User Event Handling -------------------- */ | ||
188 | |||
189 | handleKeydown : { | ||
190 | value : function(e) { | ||
191 | var k = e.keyCode; | ||
192 | console.log('keyCode: ' + k); | ||
193 | } | ||
194 | }, | ||
195 | ///// Text input has changed values | ||
196 | handleInput : { | ||
197 | value : function(e) { | ||
198 | if(!this.isDirty) { | ||
199 | this.isDirty = true; | ||
200 | } | ||
201 | |||
202 | this._sendEvent('input'); | ||
203 | } | ||
204 | }, | ||
205 | handleMouseup : { | ||
206 | value : function(e) { | ||
207 | console.log('handle mouse down'); | ||
208 | ///// Listen for simulated blur event | ||
209 | if(this.stopOnBlur && e._event.target !== this._element) { | ||
210 | this.blur(); | ||
211 | } | ||
212 | } | ||
213 | }, | ||
214 | handleEvent : { | ||
215 | value : function(e) { | ||
216 | console.log("event type : " + e._event.type); | ||
217 | ///// If configured, start on specified event | ||
218 | if(e._event.type === this.startOnEvent) { | ||
219 | this.start(); | ||
220 | } | ||
221 | } | ||
222 | }, | ||
223 | _sendEvent : { | ||
224 | value : function(type) { | ||
225 | var evt = document.createEvent("CustomEvent"); | ||
226 | evt.initCustomEvent(type, true, true); | ||
227 | this.dispatchEvent(evt); | ||
228 | } | ||
229 | }, | ||
230 | |||
231 | /* -------------------- CONFIG -------------------- */ | ||
232 | |||
233 | editingClass : { | ||
234 | value : 'editable' | ||
235 | }, | ||
236 | readOnlyClass : { | ||
237 | value : 'readOnly' | ||
238 | }, | ||
239 | selectOnStart : { | ||
240 | value : true | ||