@@ -12,23 +12,32 @@ Syntax.Editor = function(container, text) {
12
12
Syntax . Editor . prototype . getLines = function ( ) {
13
13
var children = this . container . children , lines = [ ] , offsets = [ ] ;
14
14
15
- for ( var j = 0 ; j < children . length ; j += 1 ) {
16
- if ( children [ j ] . nodeType == 3 ) {
17
- $ ( children [ j ] ) . remove ( ) ;
18
- }
19
- }
20
-
15
+ // Sometimes, e.g. when deleting text, children elements are not complete lines.
16
+ // We need to accumulate incomplete lines (1), and then append them to the
17
+ // start of the next complete line (2)
18
+ var text = "" ;
21
19
for ( var i = 0 ; i < children . length ; i += 1 ) {
22
20
var childLines = Syntax . getCDATA ( [ children [ i ] ] ) . split ( '\n' ) ;
23
21
24
- childLines . pop ( ) ;
22
+ if ( childLines . length > 1 ) {
23
+ childLines [ 0 ] = text + childLines [ 0 ] ; // (2)
24
+ text = "" ;
25
+ childLines . pop ( ) ;
26
+ } else {
27
+ text += childLines [ 0 ] ; // (1)
28
+ continue ;
29
+ }
25
30
26
31
for ( var j = 0 ; j < childLines . length ; j += 1 ) {
27
32
offsets . push ( i - lines . length ) ;
28
33
lines . push ( childLines [ j ] ) ;
29
34
}
30
35
}
31
36
37
+ offsets . push ( offsets [ offsets . length - 1 ] ) ;
38
+
39
+ Syntax . log ( offsets , lines , children ) ;
40
+
32
41
return { lines : lines , offsets : offsets } ;
33
42
}
34
43
@@ -108,7 +117,7 @@ Syntax.Editor.prototype.textForLines = function(start, end) {
108
117
}
109
118
110
119
Syntax . Editor . prototype . updateLines = function ( changed , newLines ) {
111
- console . log ( "updateLines" , changed . start , changed . originalEnd , "->" , changed . start , changed . end , changed ) ;
120
+ Syntax . log ( "updateLines" , changed . start , changed . originalEnd , "->" , changed . start , changed . end , changed ) ;
112
121
113
122
// We have two cases to handle, either we are replacing lines
114
123
// (1a) Replacing old lines with one more more new lines (update)
@@ -117,29 +126,29 @@ Syntax.Editor.prototype.updateLines = function(changed, newLines) {
117
126
// (2a) We are inserting lines at the start of the element
118
127
// (2b) We are inserting lines after an existing element.
119
128
120
- if ( changed . start != changed . originalEnd ) {
129
+ if ( changed . start != changed . end ) {
121
130
// When text is deleted, at most two elements can remain:
122
131
// (1) Whatever was partially remaining on the first line.
123
132
// (2) Whatever was partially remaining on the last line.
124
133
// All other lines have already been removed by the container.
125
134
// changed.difference tells us how many elements have already been removed.
126
135
127
136
// Cases (1a) and (1b)
128
- var start = changed . start , end = changed . originalEnd ;
137
+ var start = changed . start , end = changed . end ;
129
138
130
- if ( changed . difference < 0 )
131
- end += changed . difference ;
139
+ // if (changed.difference < 0)
140
+ // end += changed.difference;
132
141
133
- console . log ( "original" , start , end ) ;
142
+ Syntax . log ( "original" , start , end ) ;
134
143
135
144
start += this . current . offsets [ start ] ;
136
- // end += this.current.offsets[end];
145
+ end += this . current . offsets [ end ] ;
137
146
138
- console . log ( "slice" , start , end )
147
+ Syntax . log ( "slice" , start , end )
139
148
140
149
var oldLines = Array . prototype . slice . call ( this . container . children , start , end ) ;
141
150
142
- console . log ( "Replacing old lines" , oldLines , "with" , newLines ) ;
151
+ Syntax . log ( "Replacing old lines" , oldLines , "with" , newLines ) ;
143
152
144
153
$ ( oldLines ) . replaceWith ( newLines ) ;
145
154
} else {
@@ -155,31 +164,23 @@ Syntax.Editor.prototype.updateLines = function(changed, newLines) {
155
164
}
156
165
}
157
166
158
- // http://jsfiddle.net/timdown/2YcaX/3/
159
- Syntax . Editor . getCharacterOffset = function ( range , node ) {
160
- // Are \n being considered?
161
- var treeWalker = document . createTreeWalker (
162
- node ,
163
- NodeFilter . SHOW_TEXT ,
164
- function ( node ) {
165
- var nodeRange = document . createRange ( ) ;
166
- nodeRange . selectNode ( node ) ;
167
- return nodeRange . compareBoundaryPoints ( Range . END_TO_END , range ) < 1 ?
168
- NodeFilter . FILTER_ACCEPT : NodeFilter . FILTER_REJECT ;
169
- } ,
170
- false
171
- ) ;
172
-
173
- var charCount = 0 ;
174
- while ( treeWalker . nextNode ( ) ) {
175
- charCount += treeWalker . currentNode . length ;
176
- }
177
-
178
- if ( range . startContainer . nodeType == 3 ) {
179
- charCount += range . startOffset ;
167
+ // http://jsfiddle.net/TjXEG/1/
168
+ Syntax . Editor . getCharacterOffset = function ( element ) {
169
+ var caretOffset = 0 ;
170
+ if ( typeof window . getSelection != "undefined" ) {
171
+ var range = window . getSelection ( ) . getRangeAt ( 0 ) ;
172
+ var preCaretRange = range . cloneRange ( ) ;
173
+ preCaretRange . selectNodeContents ( element ) ;
174
+ preCaretRange . setEnd ( range . endContainer , range . endOffset ) ;
175
+ caretOffset = preCaretRange . toString ( ) . length ;
176
+ } else if ( typeof document . selection != "undefined" && document . selection . type != "Control" ) {
177
+ var textRange = document . selection . createRange ( ) ;
178
+ var preCaretTextRange = document . body . createTextRange ( ) ;
179
+ preCaretTextRange . moveToElementText ( element ) ;
180
+ preCaretTextRange . setEndPoint ( "EndToEnd" , textRange ) ;
181
+ caretOffset = preCaretTextRange . text . length ;
180
182
}
181
-
182
- return charCount ;
183
+ return caretOffset ;
183
184
} ;
184
185
185
186
Syntax . Editor . getNodesForCharacterOffsets = function ( offsets , node ) {
@@ -217,7 +218,7 @@ Syntax.Editor.prototype.getClientState = function() {
217
218
state . range = selection . getRangeAt ( 0 ) ;
218
219
219
220
if ( state . range ) {
220
- state . startOffset = Syntax . Editor . getCharacterOffset ( state . range , this . container ) ;
221
+ state . startOffset = Syntax . Editor . getCharacterOffset ( this . container ) ;
221
222
}
222
223
223
224
return state ;
@@ -240,14 +241,7 @@ Syntax.Editor.prototype.setClientState = function(state) {
240
241
Syntax . layouts . editor = function ( options , code /*, container*/ ) {
241
242
var container = jQuery ( '<div class="editor syntax highlighted" contentEditable="true">' ) ;
242
243
243
- // Setup the initial html for the layout
244
- code . children ( ) . each ( function ( ) {
245
- var line = document . createElement ( 'div' ) ;
246
- line . className = "source " + this . className ;
247
-
248
- line . appendChild ( this ) ;
249
- container . append ( line ) ;
250
- } ) ;
244
+ container . append ( code . children ( ) ) ;
251
245
252
246
var editor = new Syntax . Editor ( container . get ( 0 ) ) ;
253
247
@@ -256,29 +250,17 @@ Syntax.layouts.editor = function(options, code/*, container*/) {
256
250
var clientState = editor . getClientState ( ) ;
257
251
var changed = editor . updateChangedLines ( ) ;
258
252
259
-
260
-
261
253
var text = editor . textForLines ( changed . start , changed . end ) ;
262
- console . log ( "textForLines" , changed . start , changed . end , text ) ;
263
- //console .log("Updating lines from", changed.start, "to", changed.end, "original end", changed.originalEnd);
264
- //console .log("Children length", editor.container.children.length, editor.lines.length);
254
+ Syntax . log ( "textForLines" , changed . start , changed . end , text ) ;
255
+ //Syntax .log("Updating lines from", changed.start, "to", changed.end, "original end", changed.originalEnd);
256
+ //Syntax .log("Children length", editor.container.children.length, editor.lines.length);
265
257
266
258
if ( changed . start == changed . end ) {
267
259
editor . updateLines ( changed , [ ] ) ;
268
260
} else {
269
261
// Lines have been added, update the highlighting.
270
262
Syntax . highlightText ( text , options , function ( html ) {
271
- var newLines = [ ] ;
272
-
273
- html . children ( ) . each ( function ( ) {
274
- var line = document . createElement ( 'div' ) ;
275
- line . className = "source " + this . className ;
276
-
277
- line . appendChild ( this ) ;
278
- newLines . push ( line ) ;
279
- } ) ;
280
-
281
- editor . updateLines ( changed , newLines ) ;
263
+ editor . updateLines ( changed , html . children ( ) . get ( ) ) ;
282
264
283
265
// Restore cusor position/selection if possible
284
266
editor . setClientState ( clientState ) ;
@@ -298,12 +280,12 @@ Syntax.layouts.editor = function(options, code/*, container*/) {
298
280
container . bind ( 'keydown' , function ( event ) {
299
281
if ( event . keyCode == 9 ) {
300
282
event . preventDefault ( ) ;
301
- document . execCommand ( 'insertHTML' , true , " " ) ;
283
+ document . execCommand ( 'insertHTML' , false , " " ) ;
284
+ }
285
+ else if ( event . keyCode == 13 ) {
286
+ event . preventDefault ( ) ;
287
+ document . execCommand ( 'insertHTML' , false , "\n" ) ;
302
288
}
303
- // else if (event.keyCode == 13) {
304
- // event.preventDefault();
305
- // document.execCommand('insertHTML', true, "\n");
306
- //}
307
289
} ) ;
308
290
309
291
ED = editor ;
0 commit comments