Ticket #5479: 5479_14.patch
File 5479_14.patch, 12.7 KB (added by , 14 years ago) |
---|
-
_source/core/dom/element.js
234 234 this.append( new CKEDITOR.dom.text( text ) ); 235 235 }, 236 236 237 appendBogus : function()238 {239 var lastChild = this.getLast() ;240 241 // Ignore empty/spaces text.242 while ( lastChild && lastChild.type == CKEDITOR.NODE_TEXT && !CKEDITOR.tools.rtrim( lastChild.getText() ) )243 lastChild = lastChild.getPrevious();244 if ( !lastChild || !lastChild.is || !lastChild.is( 'br' ) )245 {246 var bogus = CKEDITOR.env.opera ?247 this.getDocument().createText('') :248 this.getDocument().createElement( 'br' );249 250 CKEDITOR.env.gecko && bogus.setAttribute( 'type', '_moz' );251 252 this.append( bogus );253 }254 },255 256 237 /** 257 238 * Retrieve block element's filler node if existed. 258 239 */ -
_source/core/dom/walker.js
449 449 return false; 450 450 }; 451 451 452 // Append a filler node at the end of an element if not exists. 453 CKEDITOR.dom.element.prototype.appendBogus = function() 454 { 455 var lastChild = this.getLast( fillerEvaluator ) ; 456 if ( !lastChild || !lastChild.is || !lastChild.is( 'br' ) ) 457 { 458 var bogus = CKEDITOR.env.opera ? 459 this.getDocument().createText('') : 460 this.getDocument().createElement( 'br' ); 461 462 CKEDITOR.env.gecko && bogus.setAttribute( 'type', '_moz' ); 463 464 this.append( bogus ); 465 } 466 }; 467 468 452 469 })(); -
_source/plugins/wysiwygarea/plugin.js
21 21 // Elements that could have empty new line around, including table, pre-formatted block, hr, page-break. (#6554) 22 22 function nonExitable( element ) 23 23 { 24 return ( element.getName() in nonExitableElementNames )25 || element.isBlockBoundary() && CKEDITOR.dtd.$empty[ element.getName() ] ;24 return !!( element.getName() in nonExitableElementNames 25 || element.isBlockBoundary() && CKEDITOR.dtd.$empty[ element.getName() ] ); 26 26 } 27 27 28 28 … … 38 38 39 39 insertFunc.call( this, evt.data ); 40 40 41 paddingBody( this ); 42 41 43 // Save snaps after the whole execution completed. 42 44 // This's a workaround for make DOM modification's happened after 43 45 // 'insertElement' to be included either, e.g. Form-based dialogs' 'commitContents' … … 197 199 if ( selIsLocked ) 198 200 selection.unlock(); 199 201 200 var range, clone, lastElement, bookmark; 202 var range, clone, lastElement, 203 path; 201 204 202 205 for ( var i = ranges.length - 1 ; i >= 0 ; i-- ) 203 206 { 204 207 range = ranges[ i ]; 208 path = new CKEDITOR.dom.elementPath( range.startContainer ); 205 209 206 207 208 209 210 if ( !range.checkReadOnly() ) 211 { 212 // Remove the original contents. 213 range.deleteContents(); 210 214 211 215 clone = !i && element || element.clone( 1 ); 212 216 213 // If we're inserting a block at dtd-violated position, split 214 // the parent blocks until we reach blockLimit. 215 var current, dtd; 216 if ( isBlock ) 217 { 218 while ( ( current = range.getCommonAncestor( 0, 1 ) ) 219 && ( dtd = CKEDITOR.dtd[ current.getName() ] ) 220 && !( dtd && dtd [ elementName ] ) ) 221 { 222 // Split up inline elements. 223 if ( current.getName() in CKEDITOR.dtd.span ) 224 range.splitElement( current ); 225 // If we're in an empty block which indicate a new paragraph, 226 // simply replace it with the inserting block.(#3664) 227 else if ( range.checkStartOfBlock() 228 && range.checkEndOfBlock() ) 229 { 230 range.setStartBefore( current ); 231 range.collapse( true ); 232 current.remove(); 233 } 234 else 235 range.splitBlock(); 236 } 237 } 217 // If we're inserting a block at dtd-violated position, split 218 // the parent blocks until we reach blockLimit. 219 var current, dtd; 220 if ( isBlock ) 221 { 222 while ( ( current = range.getCommonAncestor( 0, 1 ) ) 223 && ( dtd = CKEDITOR.dtd[ 224 // Is the div used as paragraph? 225 this.config.enterMode == CKEDITOR.ENTER_DIV 226 && path.block 227 && path.block.equals( current ) 228 && current.is( 'div' ) ? 'p' : current.getName() ] ) 229 && !( dtd && dtd [ elementName ] ) ) 230 { 231 // Split up inline elements. 232 if ( current.getName() in CKEDITOR.dtd.span ) 233 range.splitElement( current ); 234 // If we're in an empty block which indicate a new paragraph, 235 // simply replace it with the inserting block.(#3664) 236 else if ( range.checkStartOfBlock() 237 && range.checkEndOfBlock() ) 238 { 239 range.setStartBefore( current ); 240 range.collapse( true ); 241 current.remove(); 242 } 243 else 244 range.splitBlock(); 245 } 246 } 238 247 239 240 248 // Insert the new node. 249 range.insertNode( clone ); 241 250 242 243 244 245 246 247 251 // Save the last element reference so we can make the 252 // selection later. 253 if ( !lastElement ) 254 lastElement = clone; 255 } 256 } 248 257 249 250 251 258 if ( lastElement ) 259 { 260 range.moveToPosition( lastElement, CKEDITOR.POSITION_AFTER_END ); 252 261 253 254 255 256 257 258 262 // If we're inserting a block element immediatelly followed by 263 // another block element, the selection must move there. (#3100,#5436) 264 if ( isBlock ) 265 { 266 var next = lastElement.getNext( notWhitespaceEval ), 267 nextName = next && next.type == CKEDITOR.NODE_ELEMENT && next.getName(); 259 268 260 261 262 263 264 269 // Check if it's a block element that accepts text. 270 if ( nextName && CKEDITOR.dtd.$block[ nextName ] && CKEDITOR.dtd[ nextName ]['#'] ) 271 range.moveToElementEditStart( next ); 272 } 273 } 265 274 275 // Defer it a bit to allow other adjustment to happen. 276 setTimeout( function() 277 { 266 278 selection.selectRanges( [ range ] ); 279 }, 0 ); 267 280 268 281 if ( selIsLocked ) 269 282 this.getSelection().lock(); … … 304 317 return block.getOuterHtml().match( emptyParagraphRegexp ); 305 318 } 306 319 307 isNotWhitespace = CKEDITOR.dom.walker.whitespaces( true );308 309 320 // Gecko need a key event to 'wake up' the editing 310 321 // ability when document is empty.(#3864, #5781) 311 322 function activateEditing( editor ) … … 343 354 } 344 355 } 345 356 357 function paddingBody( editor ) 358 { 359 // IE below version 8 doesn't require this fix. 360 if ( CKEDITOR.env.ie6Compat || CKEDITOR.env.ie7Compat ) 361 return; 362 363 // All browsers are incapable to moving cursor out of certain non-exitable 364 // blocks (e.g. table, list, pre) at the end of document, make this happen by 365 // place a bogus node there, which would be later removed by dataprocessor. 366 var body = editor.document.getBody(), 367 enterMode = editor.config.enterMode, 368 selection = editor.getSelection(), 369 walkerRange = new CKEDITOR.dom.range( editor.document ), 370 walker = new CKEDITOR.dom.walker( walkerRange ); 371 372 walkerRange.selectNodeContents( body ); 373 walker.evaluator = function( node ) 374 { 375 return node.type == CKEDITOR.NODE_ELEMENT && nonExitable( node ); 376 }; 377 walker.guard = function( node, isMoveout ) 378 { 379 return !( ( node.type == CKEDITOR.NODE_TEXT && isNotWhitespace( node ) ) || isMoveout ); 380 }; 381 382 if ( walker.previous() ) 383 { 384 editor.fire( 'updateSnapshot' ); 385 restoreDirty( editor ); 386 CKEDITOR.env.ie && selection && restoreSelection( selection ); 387 388 var paddingBlock; 389 if ( enterMode != CKEDITOR.ENTER_BR ) 390 paddingBlock = body.append( new CKEDITOR.dom.element( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ); 391 else 392 paddingBlock = body; 393 394 if ( !CKEDITOR.env.ie ) 395 paddingBlock.appendBogus(); 396 else if ( paddingBlock.is( 'body' ) ) 397 { 398 // IE need at least a node to show the cursor, use a zero height br 399 // to fly under the radar, additionally wrap the br element with an extra span , 400 // so selection change event could be easily captured when cursor move inside of it. 401 var paddingNode = CKEDITOR.dom.element.createFromHtml( '<span data-cke-bogus=1>' + 402 '<br data-cke-temp=1 style="line-height:0"/></span>', editor.document ); 403 paddingBlock.append( paddingNode ); 404 } 405 } 406 } 407 346 408 /** 347 409 * Auto-fixing block-less content by wrapping paragraph (#3190), prevent 348 410 * non-exitable-block by padding extra br.(#3189) … … 359 421 360 422 CKEDITOR.env.gecko && activateEditing( editor ); 361 423 424 // Remove the padding body node used in IE. 425 if ( CKEDITOR.env.ie ) 426 { 427 var start = range.collapsed && range.startContainer; 428 if ( start.type == CKEDITOR.NODE_ELEMENT && start.is( 'span') && start.data( 'cke-bogus') ) 429 { 430 range.moveToPosition( start, CKEDITOR.POSITION_BEFORE_START ); 431 start.remove(); 432 range.select(); 433 return; 434 } 435 } 436 362 437 // When enterMode set to block, we'll establing new paragraph only if we're 363 438 // selecting inline contents right under body. (#3657) 364 439 if ( enterMode != CKEDITOR.ENTER_BR … … 396 471 { 397 472 element = fixedBlock.getPrevious( isNotWhitespace ); 398 473 if ( element && 399 element.type == CKEDITOR.NODE_ELEMENT && 400 !nonExitable( element ) ) 474 element.type == CKEDITOR.NODE_ELEMENT ) 401 475 { 402 range.moveToElementEditEnd( element ); 403 fixedBlock.remove(); 404 } 405 } 406 } 476 if ( !nonExitable( element ) ) 477 { 478 range.moveToElementEditEnd( element ); 479 fixedBlock.remove(); 480 } 481 else if ( element.getDirection() ) 482 fixedBlock.setAttribute( 'dir', element.getDirection() ); 483 } 484 } 485 } 407 486 408 487 range.select(); 409 488 // Notify non-IE that selection has changed. … … 415 494 } 416 495 } 417 496 418 // All browsers are incapable to moving cursor out of certain non-exitable 419 // blocks (e.g. table, list, pre) at the end of document, make this happen by 420 // place a bogus node there, which would be later removed by dataprocessor. 421 var walkerRange = new CKEDITOR.dom.range( editor.document ), 422 walker = new CKEDITOR.dom.walker( walkerRange ); 423 walkerRange.selectNodeContents( body ); 424 walker.evaluator = function( node ) 425 { 426 return node.type == CKEDITOR.NODE_ELEMENT && ( node.getName() in nonExitableElementNames ); 427 }; 428 walker.guard = function( node, isMoveout ) 429 { 430 return !( ( node.type == CKEDITOR.NODE_TEXT && isNotWhitespace( node ) ) || isMoveout ); 431 }; 432 433 if ( walker.previous() ) 434 { 435 editor.fire( 'updateSnapshot' ); 436 restoreDirty( editor ); 437 CKEDITOR.env.ie && restoreSelection( selection ); 438 439 var paddingBlock; 440 if ( enterMode != CKEDITOR.ENTER_BR ) 441 paddingBlock = body.append( new CKEDITOR.dom.element( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ); 442 else 443 paddingBlock = body; 444 445 if ( !CKEDITOR.env.ie ) 446 paddingBlock.appendBogus(); 447 } 448 } 497 paddingBody( editor ); 498 } 449 499 450 500 CKEDITOR.plugins.add( 'wysiwygarea', 451 501 { … … 1082 1132 var title = editor.document.getElementsByTag( 'title' ).getItem( 0 ); 1083 1133 title.data( 'cke-title', editor.document.$.title ); 1084 1134 editor.document.$.title = frameLabel; 1135 1136 paddingBody( editor ); 1137 1085 1138 }); 1086 1139 1087 1140 // IE8 stricts mode doesn't have 'contentEditable' in effect … … 1165 1218 element.data( 'cke-editable', element.hasAttribute( 'contenteditable' ) ? 'true' : '1' ); 1166 1219 element.setAttribute( 'contentEditable', false ); 1167 1220 } 1221 1222 paddingBody( editor ); 1168 1223 }); 1169 1224 1170 }1171 });1225 } 1226 }); 1172 1227 1173 1228 // Fixing Firefox 'Back-Forward Cache' break design mode. (#4514) 1174 1229 if ( CKEDITOR.env.gecko )