Ticket #3304: 3304_4.patch
File 3304_4.patch, 11.5 KB (added by , 14 years ago) |
---|
-
_source/plugins/find/dialogs/find.js
5 5 6 6 (function() 7 7 { 8 // Element tag names which prevent characters counting. 9 var characterBoundaryElementsEnum = 8 function guardDomWalkerNonEmptyTextNode( node ) 10 9 { 11 address :1, blockquote :1, dl :1, h1 :1, h2 :1, h3 :1, 12 h4 :1, h5 :1, h6 :1, p :1, pre :1, li :1, dt :1, de :1, div :1, td:1, th:1 13 }; 10 if ( node.type == CKEDITOR.NODE_TEXT && node.$.length > 0 ) 11 return true; 12 else 13 return false; 14 } 14 15 15 var guardDomWalkerNonEmptyTextNode = function( evt ) 16 /** 17 * Elements which break characters been considered as sequence. 18 */ 19 function checkCharactersBoundary ( node ) 16 20 { 17 if ( evt.data.to && evt.data.to.type == CKEDITOR.NODE_TEXT 18 && evt.data.to.$.length > 0 ) 19 this.stop(); 20 CKEDITOR.dom.domWalker.blockBoundary( { br : 1 } ).call( this, evt ); 21 }; 22 21 var dtd = CKEDITOR.dtd; 22 return node.isBlockBoundary( 23 CKEDITOR.tools.extend( {}, dtd.$empty, dtd.$nonEditable ) ); 24 } 23 25 24 26 /** 25 27 * Get the cursor object which represent both current character and it's dom … … 75 77 * Iterator which walk through document char by char. 76 78 * @param {Object} start 77 79 * @param {Number} offset 80 * @param {Boolean} isStrict 78 81 */ 79 var characterWalker = function( start, offset )82 var characterWalker = function( start, offset , isStrict ) 80 83 { 81 84 var isCursor = typeof( start.textNode ) !== 'undefined'; 82 85 this.textNode = isCursor ? start.textNode : start; … … 81 84 var isCursor = typeof( start.textNode ) !== 'undefined'; 82 85 this.textNode = isCursor ? start.textNode : start; 83 86 this.offset = isCursor ? start.offset : offset; 87 var walker = new CKEDITOR.dom.walker( this.textNode ); 88 walker[ isStrict? 'guard' : 'evaluator' ] = 89 guardDomWalkerNonEmptyTextNode; 84 90 this._ = { 85 walker : new CKEDITOR.dom.domWalker( this.textNode ),91 walker : walker, 86 92 matchBoundary : false 87 93 }; 88 94 }; … … 107 113 108 114 // If we are at the end of the text node, use dom walker to get 109 115 // the next text node. 110 var data = null; 111 while ( !data || ( data.node && data.node.type != 112 CKEDITOR.NODE_TEXT ) ) 116 var node = null; 117 while ( !node ) 113 118 { 114 data = this._.walker.forward( 115 guardDomWalkerNonEmptyTextNode ); 119 node = this._.walker.next( true ); 116 120 117 // Block boundary? BR? Document boundary? 118 if ( !data.node 119 || ( data.node.type !== CKEDITOR.NODE_TEXT 120 && data.node.getName() in 121 characterBoundaryElementsEnum ) ) 121 // Marking as match boundaries. 122 if( node === false 123 && checkCharactersBoundary( this._.walker.current ) ) 122 124 this._.matchBoundary = true; 125 // Already reach document end. 126 if ( !this._.walker.current ) 127 break; 128 123 129 } 124 this.textNode = data.node;130 this.textNode = node; 125 131 this.offset = 0; 126 132 return cursorStep.call( this ); 127 133 }, … … 138 144 } 139 145 140 146 // Start of text node -> use dom walker to get the previous text node. 141 var data = null; 142 while ( !data 143 || ( data.node && data.node.type != CKEDITOR.NODE_TEXT ) ) 147 var node = null; 148 while ( !node ) 144 149 { 145 data = this._.walker.reverse( guardDomWalkerNonEmptyTextNode );150 node = this._.walker.previous( true ); 146 151 147 // Block boundary? BR? Document boundary?148 if ( !data.node || ( data.node.type !== CKEDITOR.NODE_TEXT &&149 data.node.getName() in characterBoundaryElementsEnum) )152 // Marking as match boundaries. 153 if( node === false 154 && checkCharactersBoundary( this._.walker.current ) ) 150 155 this._.matchBoundary = true; 156 157 // Already reach document end. 158 if ( !this._.walker.current ) 159 break; 151 160 } 152 this.textNode = data.node;153 this.offset = data.node.length - 1;161 this.textNode = node; 162 this.offset = node.length - 1; 154 163 return cursorStep.call( this ); 155 164 } 156 165 }; … … 465 474 var cursors = this.range.getCursors(), 466 475 tail = cursors[ cursors.length - 1 ], 467 476 head = cursors[ 0 ], 468 headWalker = new characterWalker( head ),469 tailWalker = new characterWalker( tail );477 headWalker = new characterWalker( head, null, true ), 478 tailWalker = new characterWalker( tail, null, true ); 470 479 471 480 if ( ! ( isWordSeparator( 472 481 headWalker.back().character ) -
_source/core/loader.js
39 39 'core/dom/node' : [ 'core/dom/domobject', 'core/tools' ], 40 40 'core/dom/nodelist' : [ 'core/dom/node' ], 41 41 'core/dom/domobject' : [ 'core/dom/event' ], 42 'core/dom/domwalker' : [ 'core/dom/node', 'core/dom/element', 'core/dom/document' ], 43 'core/dom/range' : [ 'core/dom/document', 'core/dom/documentfragment', 'core/dom/element', 'core/dom/domwalker', 'core/dom/walker' ], 42 'core/dom/range' : [ 'core/dom/document', 'core/dom/documentfragment', 'core/dom/element', 'core/dom/walker' ], 44 43 'core/dom/text' : [ 'core/dom/node', 'core/dom/domobject' ], 45 44 'core/dom/walker' : [ 'core/dom/node' ], 46 45 'core/dom/window' : [ 'core/dom/domobject' ], -
_source/core/dom/range.js
366 366 */ 367 367 createBookmark : function( serializable ) 368 368 { 369 var startNode, endNode;369 var bookmark, startNode, endNode; 370 370 var baseId; 371 371 var clone; 372 372 … … 410 410 } 411 411 else 412 412 this.moveToPosition( startNode, CKEDITOR.POSITION_AFTER_END ); 413 414 return {413 414 return ( bookmark = { 415 415 startNode : serializable ? baseId + 'S' : startNode, 416 416 endNode : serializable ? baseId + 'E' : endNode, 417 serializable : serializable 418 }; 417 serializable : serializable, 418 419 /** 420 * Drop the bookmark nodes from the document when 421 * 'moveToBookmark' is never invoked since it's been 422 * used as marker node. 423 */ 424 destroy : CKEDITOR.tools.bind( function() 425 { 426 var bm = this.createBookmark(); 427 this.moveToBookmark( bookmark ); 428 this.moveToBookmark( bm ); 429 }, this ) 430 } ); 419 431 }, 420 432 421 433 /** … … 1088 1100 case CKEDITOR.ENLARGE_BLOCK_CONTENTS: 1089 1101 case CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS: 1090 1102 // DFS backward to get the block/list item boundary at or before the start. 1091 1092 // Get the boundaries nodes.1093 var startNode = this.getTouchedStartNode(),1094 endNode = this.getTouchedEndNode();1095 1096 if ( startNode.type == CKEDITOR.NODE_ELEMENT && startNode.isBlockBoundary())1103 // Get the outter boundaries nodes. 1104 var startNode, endNode; 1105 1106 // Use bookmark nodes to mock boundary nodes for collapsed 1107 // range. 1108 if( this.collapsed ) 1097 1109 { 1098 this.setStartAt( startNode, 1099 CKEDITOR.dtd.$empty[ startNode.getName() ] ? 1100 CKEDITOR.POSITION_AFTER_END : 1101 CKEDITOR.POSITION_AFTER_START ); 1110 var bm = this.createBookmark(); 1111 startNode= bm.startNode; 1112 endNode = startNode; 1102 1113 } 1103 1114 else 1104 1115 { 1105 // Get the function used to check the enlaarging limits. 1106 var guardFunction = ( unit == CKEDITOR.ENLARGE_BLOCK_CONTENTS ? 1107 CKEDITOR.dom.domWalker.blockBoundary() : 1108 CKEDITOR.dom.domWalker.listItemBoundary() ); 1109 1110 // Create the DOM walker, which will traverse the DOM. 1111 var walker = new CKEDITOR.dom.domWalker( startNode ); 1116 var boundaries = this.getBoundaryNodes(), 1117 startNode = boundaries.startNode, 1118 endNode = boundaries.endNode; 1119 } 1112 1120 1113 // Go walk in reverse sense. 1114 var data = walker.reverse( guardFunction ); 1121 // Enlarging the start and end boundary. 1122 var walker = new CKEDITOR.dom.walker( startNode ), 1123 enlargeable, 1124 blockGuard = 1125 CKEDITOR.dom.walker.blockBoundary( 1126 CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS ? { br : 1 } : null ); 1127 walker.guard = blockGuard; 1128 // The walker could only check sibling since block could 1129 // never be berried as children of inline elements. 1130 walker.startFromSibling = true; 1131 if ( enlargeable = walker.lastBackward() ) 1132 this.setStartAt( enlargeable, CKEDITOR.POSITION_BEFORE_START ); 1115 1133 1116 var boundaryEvent = data.events.shift(); 1134 walker.reset(); 1135 walker.startNode = endNode; 1136 if ( enlargeable = walker.lastForward() ) 1137 this.setEndAt( enlargeable, CKEDITOR.POSITION_AFTER_END ); 1117 1138 1118 this.setStartBefore( boundaryEvent.from ); 1119 } 1120 1121 if ( endNode.type == CKEDITOR.NODE_ELEMENT && endNode.isBlockBoundary() ) 1122 { 1123 this.setEndAt( endNode, 1124 CKEDITOR.dtd.$empty[ endNode.getName() ] ? 1125 CKEDITOR.POSITION_BEFORE_START : 1126 CKEDITOR.POSITION_BEFORE_END ); 1127 } 1128 else 1129 { 1130 // DFS forward to get the block/list item boundary at or before the end. 1131 walker.setNode( endNode ); 1132 data = walker.forward( guardFunction ); 1133 boundaryEvent = data.events.shift(); 1134 1135 this.setEndAfter( boundaryEvent.from ); 1136 } 1139 if( bm ) 1140 bm.destroy(); 1137 1141 } 1138 1142 }, 1139 1143 -
_source/core/dom/walker.js
44 44 node = null; 45 45 } 46 46 else 47 node = this.startNode[ getSourceNodeFn ]( true, type, guard );47 node = this.startNode[ getSourceNodeFn ]( false, type, guard ); 48 48 49 49 while ( node && !this._.end ) 50 50 { … … 217 217 checkBackward : function() 218 218 { 219 219 return iterate.call( this, true, true ) !== false; 220 }, 221 222 /** 223 * Reset walker to initial state. 224 */ 225 reset : function() 226 { 227 delete this._.end; 228 delete this.current; 220 229 } 221 230 } 222 231 }); 232 233 /* 234 * Anything whose display computed style is block, list-item, table, 235 * table-row-group, table-header-group, table-footer-group, table-row, 236 * table-column-group, table-column, table-cell, table-caption, or whose node 237 * name is hr, br (when enterMode is br only) is a block boundary. 238 */ 239 var blockBoundaryDisplayMatch = 240 { 241 block : 1, 242 'list-item' : 1, 243 table : 1, 244 'table-row-group' : 1, 245 'table-header-group' : 1, 246 'table-footer-group' : 1, 247 'table-row' : 1, 248 'table-column-group' : 1, 249 'table-column' : 1, 250 'table-cell' : 1, 251 'table-caption' : 1 252 }, 253 blockBoundaryNodeNameMatch = { hr : 1 }; 254 255 CKEDITOR.dom.element.prototype.isBlockBoundary = function( customNodeNames ) 256 { 257 var nodeNameMatches = CKEDITOR.tools.extend( 258 blockBoundaryNodeNameMatch, customNodeNames || {} ); 259 260 return blockBoundaryDisplayMatch[ this.getComputedStyle( 'display' ) ] || 261 nodeNameMatches[ this.getName() ]; 262 }; 263 264 CKEDITOR.dom.walker.blockBoundary = function( customNodeNames ) 265 { 266 return function( node , type ) 267 { 268 return ! ( node.type == CKEDITOR.NODE_ELEMENT 269 && node.isBlockBoundary( customNodeNames ) ); 270 }; 271 }; 272 273 CKEDITOR.dom.walker.listItemBoundary = function() 274 { 275 return this.blockBoundary( { br : 1 } ); 276 }; 277 223 278 })();