Ticket #3189: 3189_3.patch
File 3189_3.patch, 9.2 KB (added by , 15 years ago) |
---|
-
_source/plugins/wysiwygarea/plugin.js
10 10 11 11 (function() 12 12 { 13 /** 14 * List of elements in which has no way to move editing focus outside. 15 */ 16 var nonExitableElementNames = { table:1,pre:1 }; 17 13 18 function onInsertHtml( evt ) 14 19 { 15 20 if ( this.mode == 'wysiwyg' ) … … 71 76 72 77 clone = !i && element || element.clone( true ); 73 78 74 var toSplit;75 76 // If the new node is a block element, split the current block (if any).79 // If we're inserting a block at dtd-violated positoin, split 80 // the parent blocks until we reach blockLimit. 81 var parent, dtd; 77 82 if ( this.config.enterMode != CKEDITOR.ENTER_BR && isBlock ) 78 {79 var startPath = new CKEDITOR.dom.elementPath( range.startContainer ),80 j = 0,81 parent;83 while( ( parent = range.getCommonAncestor( false, true ) ) 84 && ( dtd = CKEDITOR.dtd[ parent.getName() ] ) 85 && !( dtd && dtd [ elementName ] ) ) 86 range.splitBlock(); 82 87 83 while( ( parent = startPath.elements[ j++ ] ) && parent != startPath.blockLimit )84 {85 var parentName = parent.getName(),86 parentDtd = CKEDITOR.dtd[ parentName ];87 88 if ( parentDtd && !parentDtd[ elementName ] )89 toSplit = parent;90 }91 }92 93 88 // Insert the new node. 94 89 range.insertNode( clone ); 95 90 96 if ( toSplit )97 clone.breakParent( toSplit );98 99 91 // Save the last element reference so we can make the 100 92 // selection later. 101 93 if ( !lastElement ) … … 114 106 this.getSelection().lock(); 115 107 } 116 108 } 117 109 110 /** 111 * Auto-fixing block-less content by wrapping paragraph, prevent 112 * non-exitable-block by padding extra br. 113 */ 114 function onSelectionChangeFixBody( evt ) 115 { 116 var editor = evt.editor, 117 path = evt.data.path, 118 blockLimit = path.blockLimit, 119 body = editor.document.getBody(), 120 enterMode = editor.config.enterMode; 121 122 // When enterMode set to block, we'll establing new paragraph if the 123 // current range is block-less within body. 124 if ( enterMode != CKEDITOR.ENTER_BR 125 && blockLimit.getName() == 'body' 126 && !path.block ) 127 { 128 var selection = evt.data.selection, 129 range = evt.data.selection.getRanges()[0], 130 bms = selection.createBookmarks(), 131 fixedBlock = range.fixBlock( true, 132 editor.config.enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p' ); 133 134 // For IE, we'll be removing any bogus br ( introduce by fixing body ) 135 // right now to prevent it introducing visual line break. 136 if ( CKEDITOR.env.ie ) 137 { 138 var brNodeList = fixedBlock.getElementsByTag( 'br' ), brNode; 139 for ( var i = 0 ; i < brNodeList.count() ; i++ ) 140 if( ( brNode = brNodeList.getItem( i ) ) && brNode.hasAttribute( '_fck_bookmark' ) ) 141 brNode.remove(); 142 } 143 144 selection.selectBookmarks( bms ); 145 } 146 147 // Inserting the padding-br before body if it's preceded by an 148 // unexitable block. 149 var lastNode = body.getLast( true ); 150 if ( lastNode.getName && ( lastNode.getName() in nonExitableElementNames ) ) 151 { 152 var paddingBlock = editor.document.createElement( 153 ( CKEDITOR.env.ie && enterMode != CKEDITOR.ENTER_BR ) ? 154 '<br _cke_bogus="true" />' : 'br' ); 155 body.append( paddingBlock ); 156 } 157 } 158 118 159 CKEDITOR.plugins.add( 'wysiwygarea', 119 160 { 120 161 requires : [ 'editingblock' ], … … 449 490 450 491 editor.on( 'insertHtml', onInsertHtml, null, null, 20 ); 451 492 editor.on( 'insertElement', onInsertElement, null, null, 20 ); 493 // Auto fixing on some document structure weakness to enhance usabilities. (#3190 and #3189) 494 editor.on( 'selectionChange', onSelectionChangeFixBody, null, null, 1 ); 452 495 }); 453 496 } 454 497 }); -
_source/core/dom/element.js
643 643 return $ ? new CKEDITOR.dom.node( $ ) : null; 644 644 }, 645 645 646 getLast : function() 646 /** 647 * @param ignoreEmpty Skip empty text nodes. 648 */ 649 getLast : function( ignoreEmpty ) 647 650 { 648 651 var $ = this.$.lastChild; 649 return $ ? new CKEDITOR.dom.node( $ ) : null; 652 if ( ignoreEmpty && $ && ( $.nodeType == CKEDITOR.NODE_TEXT ) 653 && !CKEDITOR.tools.trim( $.nodeValue ) ) 654 return new CKEDITOR.dom.node( $ ).getPrevious( true ); 655 else 656 return $ ? new CKEDITOR.dom.node( $ ) : null; 650 657 }, 651 658 652 659 getStyle : function( name ) -
_source/core/dom/node.js
259 259 return -1; 260 260 }, 261 261 262 /**263 * Gets the node following this node (next sibling).264 * @returns {CKEDITOR.dom.node} The next node.265 */266 getNext : function()267 {268 var next = this.$.nextSibling;269 return next ? new CKEDITOR.dom.node( next ) : null;270 },271 272 262 getNextSourceNode : function( startFromSibling, nodeType, guard ) 273 263 { 274 264 // If "guard" is a node, transform it in a function. … … 360 350 return node; 361 351 }, 362 352 363 getPrevious : function( )353 getPrevious : function( ignoreSpaces ) 364 354 { 365 355 var previous = this.$.previousSibling; 356 while ( ignoreSpaces && previous && ( previous.nodeType == CKEDITOR.NODE_TEXT ) 357 && !CKEDITOR.tools.trim( previous.nodeValue ) ) 358 previous = previous.previousSibling; 359 366 360 return previous ? new CKEDITOR.dom.node( previous ) : null; 367 361 }, 368 362 369 363 /** 370 364 * Gets the node that follows this element in its parent's child list. 365 * @param {Boolean} ignoreSpaces Whether should ignore empty text nodes. 371 366 * @returns {CKEDITOR.dom.node} The next node or null if not 372 367 * available. 373 368 * @example … … 375 370 * var first = <b>element.getFirst().getNext()</b>; 376 371 * alert( first.getName() ); // "i" 377 372 */ 378 getNext : function( )373 getNext : function( ignoreSpaces ) 379 374 { 380 var $ = this.$.nextSibling; 381 return $ ? new CKEDITOR.dom.node( $ ) : null; 375 var next = this.$.nextSibling; 376 while ( ignoreSpaces && next && ( next.nodeType == CKEDITOR.NODE_TEXT ) 377 && !CKEDITOR.tools.trim( next.nodeValue ) ) 378 next = next.nextSibling; 379 380 return next ? new CKEDITOR.dom.node( next ) : null; 382 381 }, 383 382 384 383 /** -
_source/core/dom/range.js
31 31 // V2 32 32 var execContentsAction = function( range, action, docFrag ) 33 33 { 34 range.optimizeBookmark(); 35 34 36 var startNode = range.startContainer; 35 37 var endNode = range.endContainer; 36 38 … … 607 609 return { startNode : startNode, endNode : endNode }; 608 610 }, 609 611 610 getCommonAncestor : function( includeSelf ) 612 /** 613 * Find the node which fully contains the range. 614 * @param includeSelf 615 * @param {Boolean} ignoreTextNode Whether ignore CKEDITOR.NODE_TEXT type. 616 */ 617 getCommonAncestor : function( includeSelf , ignoreTextNode ) 611 618 { 612 var start = this.startContainer; 613 var end = this.endContainer; 619 var start = this.startContainer, 620 end = this.endContainer, 621 ancestor; 614 622 615 623 if ( start.equals( end ) ) 616 624 { 617 if ( includeSelf && start.type == CKEDITOR.NODE_ELEMENT && this.startOffset == this.endOffset - 1 ) 618 return start.getChild( this.startOffset ); 619 return start; 625 if ( includeSelf 626 && start.type == CKEDITOR.NODE_ELEMENT 627 && this.startOffset == this.endOffset - 1 ) 628 ancestor = start.getChild( this.startOffset ); 629 else 630 ancestor = start; 620 631 } 632 else 633 ancestor = start.getCommonAncestor( end ); 621 634 622 return start.getCommonAncestor( end );635 return ignoreTextNode && !ancestor.is ? ancestor.getParent() : ancestor; 623 636 }, 624 637 625 638 /** … … 653 666 } 654 667 }, 655 668 669 /** 670 * Move the range out of bookmark nodes if they're been the container. 671 */ 672 optimizeBookmark: function() 673 { 674 var startNode = this.startContainer, 675 endNode = this.endContainer; 676 677 if ( startNode.is && startNode.is( 'span' ) 678 && startNode.hasAttribute( '_fck_bookmark' ) ) 679 this.setStartAt( startNode, CKEDITOR.POSITION_BEFORE_START ); 680 if ( endNode && endNode.is && endNode.is( 'span' ) 681 && endNode.hasAttribute( '_fck_bookmark' ) ) 682 this.setEndAt( endNode, CKEDITOR.POSITION_AFTER_END ); 683 }, 684 656 685 trim : function( ignoreStart, ignoreEnd ) 657 686 { 658 687 var startContainer = this.startContainer; … … 1136 1165 */ 1137 1166 insertNode : function( node ) 1138 1167 { 1168 this.optimizeBookmark(); 1139 1169 this.trim( false, true ); 1140 1170 1141 1171 var startContainer = this.startContainer; … … 1326 1356 endBlock = endPath.block; 1327 1357 1328 1358 var elementPath = null; 1329 1330 1359 // Do nothing if the boundaries are in different block limits. 1331 1360 if ( !startBlockLimit.equals( endBlockLimit ) ) 1332 1361 return null;