Ticket #3176: 3176_2.patch
File 3176_2.patch, 8.3 KB (added by , 14 years ago) |
---|
-
_source/plugins/find/dialogs/find.js
8 8 // Element tag names which prevent characters counting. 9 9 var characterBoundaryElementsEnum = 10 10 { 11 address :1, blockquote :1, dl :1, h1 :1, h2 :1, h3 :1,11 body :1, address :1, blockquote :1, dl :1, h1 :1, h2 :1, h3 :1, 12 12 h4 :1, h5 :1, h6 :1, p :1, pre :1, li :1, dt :1, de :1, div :1, td:1, th:1 13 13 }; 14 14 … … 27 27 */ 28 28 var cursorStep = function() 29 29 { 30 if( !this.textNode ) 31 return null; 32 30 33 var obj = { 31 34 textNode : this.textNode, 32 35 offset : this.offset, 33 character : this.textNode ? this.textNode.getText().charAt( this.offset ) : null,36 character : this.textNode.getText().charAt( this.offset ), 34 37 hitMatchBoundary : this._.matchBoundary 35 38 }; 36 39 return obj; … … 88 91 }; 89 92 90 93 characterWalker.prototype = { 94 95 current : function() 96 { 97 return cursorStep.call( this ); 98 }, 99 91 100 next : function() 92 101 { 93 102 // Already at the end of document, no more character available. … … 107 116 108 117 // If we are at the end of the text node, use dom walker to get 109 118 // the next text node. 110 var data = null; 111 while ( !data || ( data.node && data.node.type != 112 CKEDITOR.NODE_TEXT ) ) 119 var data; 120 do 113 121 { 114 122 data = this._.walker.forward( 115 123 guardDomWalkerNonEmptyTextNode ); … … 119 127 || ( data.node.type !== CKEDITOR.NODE_TEXT 120 128 && data.node.getName() in 121 129 characterBoundaryElementsEnum ) ) 130 { 122 131 this._.matchBoundary = true; 132 133 // Scope to content within body. 134 if ( data.node && data.node.getName() == 'body' ) 135 { 136 data.textNode = null; 137 break; 138 } 139 } 123 140 } 141 while ( data.node && data.node.type != CKEDITOR.NODE_TEXT ); 142 124 143 this.textNode = data.node; 125 144 this.offset = 0; 126 145 return cursorStep.call( this ); … … 128 147 129 148 back : function() 130 149 { 150 // Already at the start of document, no more character available. 151 if( this.textNode == null ) 152 return null; 153 131 154 this._.matchBoundary = false; 132 155 133 156 // More characters -> decrement offset and return. … … 139 162 140 163 // Start of text node -> use dom walker to get the previous text node. 141 164 var data = null; 142 while ( !data 143 || ( data.node && data.node.type != CKEDITOR.NODE_TEXT ) ) 165 do 144 166 { 145 167 data = this._.walker.reverse( guardDomWalkerNonEmptyTextNode ); 146 168 147 169 // Block boundary? BR? Document boundary? 148 170 if ( !data.node || ( data.node.type !== CKEDITOR.NODE_TEXT && 149 171 data.node.getName() in characterBoundaryElementsEnum ) ) 172 { 150 173 this._.matchBoundary = true; 174 175 // Scope to characters within body 176 if ( data.node && data.node.getName() == 'body' ) 177 { 178 data.node = null; 179 break; 180 } 181 } 151 182 } 183 while ( data.node && data.node.type != CKEDITOR.NODE_TEXT ); 184 152 185 this.textNode = data.node; 153 this.offset = data.node.length - 1;186 this.offset = this.textNode? data.node.length - 1 : 0; 154 187 return cursorStep.call( this ); 155 188 } 156 189 }; … … 194 227 var startNode = domRange.startContainer, 195 228 startIndex = domRange.startOffset, 196 229 endNode = domRange.endContainer, 197 endIndex = domRange.endOffset, 198 boundaryNodes = domRange.getBoundaryNodes(); 230 endIndex = domRange.endOffset; 199 231 200 232 if ( startNode.type != CKEDITOR.NODE_TEXT ) 201 233 { 202 startNode = boundaryNodes.startNode;234 startNode = domRange.getTouchedStartNode(); 203 235 while ( startNode.type != CKEDITOR.NODE_TEXT ) 204 startNode = startNode.get First();236 startNode = startNode.getNextSourceNode(); 205 237 startIndex = 0; 206 238 } 207 239 208 240 if ( endNode.type != CKEDITOR.NODE_TEXT ) 209 241 { 210 endNode = boundaryNodes.endNode;242 endNode = domRange.getTouchedEndNode(); 211 243 while ( endNode.type != CKEDITOR.NODE_TEXT ) 212 endNode = endNode.get Last();213 endIndex = endNode.getLength() ;244 endNode = endNode.getPreviousSourceNode(); 245 endIndex = endNode.getLength() - 1; 214 246 } 215 247 216 248 // If the endNode is an empty text node, our walker would just walk through 217 249 // it without stopping. So need to backtrack to the nearest non-emtpy text 218 250 // node. 219 if ( endNode .getLength() < 1 )251 if ( endNode && endNode.getLength() < 1 ) 220 252 { 221 253 while ( ( endNode = endNode.getPreviousSourceNode() ) && !( endNode.type == CKEDITOR.NODE_TEXT && endNode.getLength() > 0 ) ) 222 { /*jsl:pass*/ } 223 224 endIndex = endNode.getLength(); 254 endIndex = endNode.getLength() - 1; 225 255 } 226 256 227 var cursor = new characterWalker( startNode, startIndex ); 228 this._.cursors = [ cursor ]; 229 if ( !( cursor.textNode.equals( endNode ) && cursor.offset == endIndex - 1 ) ) 257 var walker = new characterWalker( startNode, startIndex ), cursor; 258 259 // DomRange contains at least one character. 260 ( this._.cursors = [] ).push( cursor = walker.current() ); 261 do 230 262 { 231 do 232 { 233 cursor = new characterWalker( cursor ); 234 cursor.next(); 235 this._.cursors.push( cursor ); 236 } 237 while ( !( cursor.textNode.equals( endNode ) && cursor.offset == endIndex - 1 ) ); 263 cursor = walker.next(); 264 this._.cursors.push( cursor ); 238 265 } 266 while ( !( cursor.textNode.equals( endNode ) && cursor.offset == endIndex ) ); 239 267 240 268 this._.rangeLength = this._.cursors.length; 241 269 }, … … 303 331 var retval = this._.walker.back(), 304 332 cursors = this._.cursors; 305 333 306 if ( retval.hitMatchBoundary )334 if ( !retval || retval.hitMatchBoundary ) 307 335 this._.cursors = cursors = []; 308 336 if( retval ) 337 { 309 338 cursors.unshift( retval ); 310 339 if ( cursors.length > this._.rangeLength ) 311 340 cursors.pop(); 341 } 312 342 313 343 return retval; 314 344 }, … … 319 349 cursors = this._.cursors; 320 350 321 351 // Clear the cursors queue if we've crossed a match boundary. 322 if ( retval.hitMatchBoundary )352 if ( !retval || retval.hitMatchBoundary ) 323 353 this._.cursors = cursors = []; 354 355 if ( retval ) 356 { 357 cursors.push( retval ); 358 if ( cursors.length > this._.rangeLength ) 359 cursors.shift(); 360 } 324 361 325 cursors.push( retval );326 if ( cursors.length > this._.rangeLength )327 cursors.shift();328 329 362 return retval; 330 363 }, 331 364 … … 454 487 matchState = matcher.feedCharacter( character ); 455 488 if ( matchState == KMP_MATCHED ) 456 489 break; 457 if ( this.range.moveNext().hitMatchBoundary ) 490 var next = this.range.moveNext(); 491 if ( next && next.hitMatchBoundary ) 458 492 matcher.reset(); 459 493 } 460 494 … … 466 500 tail = cursors[ cursors.length - 1 ], 467 501 head = cursors[ 0 ], 468 502 headWalker = new characterWalker( head ), 469 tailWalker = new characterWalker( tail ); 503 tailWalker = new characterWalker( tail ), 504 headBoundaryCursor = headWalker.back(), 505 tailBoundaryCursor = tailWalker.next(); 470 506 471 if ( ! ( isWordSeparator( 472 headWalker.back().character ) 473 && isWordSeparator( 474 tailWalker.next().character ) ) ) 475 continue; 507 if ( !( ( !headBoundaryCursor 508 || headBoundaryCursor.hitMatchBoundary 509 || isWordSeparator( headBoundaryCursor.character ) ) 510 && 511 ( !tailBoundaryCursor 512 || tailBoundaryCursor.hitMatchBoundary 513 || isWordSeparator( tailBoundaryCursor.character ) ) ) ) 514 { 515 matchState = KMP_NOMATCH; 516 matcher.reset(); 517 continue; 518 } 476 519 } 477 520 478 521 this.range.setMatched(); -
_source/core/dom/range.js
1525 1525 if ( this.collapsed || container.type != CKEDITOR.NODE_ELEMENT ) 1526 1526 return container ; 1527 1527 1528 return container.getChild [ this.endOffset - 1 ]|| container ;1528 return container.getChild( this.endOffset - 1 )|| container ; 1529 1529 } 1530 1530 }; 1531 1531 })();