Changeset 774
- Timestamp:
- 2007-09-04 16:34:12 (15 months ago)
- Location:
- FCKeditor/trunk
- Files:
-
- 12 added
- 4 removed
- 35 modified
-
editor/css/fck_editorarea.css (modified) (1 diff)
-
editor/dtd (added)
-
editor/dtd/fck_dtd_test.html (added)
-
editor/dtd/fck_xhtml10strict.js (added)
-
editor/dtd/fck_xhtml10transitional.js (added)
-
editor/fckeditor.html (modified) (6 diffs)
-
editor/_source/classes/fckdomrange_gecko.js (modified) (1 diff)
-
editor/_source/classes/fckdomrange_ie.js (modified) (2 diffs)
-
editor/_source/classes/fckdomrange.js (modified) (12 diffs)
-
editor/_source/classes/fckspecialcombo.js (modified) (3 diffs)
-
editor/_source/classes/fckstyledef_gecko.js (deleted)
-
editor/_source/classes/fckstyledef_ie.js (deleted)
-
editor/_source/classes/fckstyledef.js (deleted)
-
editor/_source/classes/fckstyle.js (added)
-
editor/_source/classes/fckstylesloader.js (deleted)
-
editor/_source/classes/fcktoolbarfontformatcombo.js (modified) (4 diffs)
-
editor/_source/classes/fcktoolbarfontscombo.js (modified) (2 diffs)
-
editor/_source/classes/fcktoolbarfontsizecombo.js (modified) (2 diffs)
-
editor/_source/classes/fcktoolbarstylecombo.js (modified) (3 diffs)
-
editor/_source/classes/fckw3crange.js (modified) (1 diff)
-
editor/_source/classes/fckxml_gecko.js (modified) (1 diff)
-
editor/_source/classes/fckxml_ie.js (modified) (1 diff)
-
editor/_source/commandclasses/fckcorestylecommand.js (added)
-
editor/_source/commandclasses/fck_othercommands.js (modified) (1 diff)
-
editor/_source/commandclasses/fckremoveformatcommand.js (added)
-
editor/_source/commandclasses/fckstylecommand.js (modified) (1 diff)
-
editor/_source/commandclasses/fcktextcolorcommand.js (modified) (1 diff)
-
editor/_source/fckconstants.js (modified) (1 diff)
-
editor/_source/fckjscoreextensions.js (modified) (1 diff)
-
editor/_source/fckscriptloader.js (modified) (3 diffs)
-
editor/_source/internals/fckcommands.js (modified) (3 diffs)
-
editor/_source/internals/fckdomtools.js (modified) (6 diffs)
-
editor/_source/internals/fck_gecko.js (modified) (1 diff)
-
editor/_source/internals/fck.js (modified) (2 diffs)
-
editor/_source/internals/fcklistslib.js (modified) (2 diffs)
-
editor/_source/internals/fckregexlib.js (modified) (2 diffs)
-
editor/_source/internals/fckselection_gecko.js (modified) (5 diffs)
-
editor/_source/internals/fckselection_ie.js (modified) (2 diffs)
-
editor/_source/internals/fckstyles.js (added)
-
editor/_source/internals/fcktools.js (modified) (1 diff)
-
editor/_source/internals/fckxhtml.js (modified) (5 diffs)
-
fckconfig.js (modified) (4 diffs)
-
fckeditor.cfc (modified) (1 diff)
-
fckeditor.cfm (modified) (1 diff)
-
fckpackager.xml (modified) (9 diffs)
-
fckstyles.xml (modified) (2 diffs)
-
_test/automated/tests/fckdomtools.html (added)
-
_test/manual/fckdomrange/test1.html (modified) (1 diff)
-
_test/manual/fckstyle (added)
-
_test/manual/fckstyle/test1.html (added)
-
_test/manual/fckstyle/test1_inner.html (added)
Legend:
- Unmodified
- Added
- Removed
-
FCKeditor/trunk/editor/css/fck_editorarea.css
r701 r774 41 41 body, td 42 42 { 43 font-family: Arial, Verdana, Sans-Serif;43 font-family: Arial, Verdana, sans-serif; 44 44 font-size: 12px; 45 45 } -
FCKeditor/trunk/editor/fckeditor.html
r701 r774 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> 2 2 <!-- 3 3 * FCKeditor - The text editor for Internet - http://www.fckeditor.net … … 86 86 LoadScript( '_source/classes/fckkeystrokehandler.js' ) ; 87 87 88 LoadScript( 'dtd/fck_xhtml10transitional.js' ) ; 89 LoadScript( '_source/classes/fckstyle.js' ) ; 90 LoadScript( '_source/internals/fckstyles.js' ) ; 91 88 92 LoadScript( '_source/internals/fcklisthandler.js' ) ; 89 93 LoadScript( '_source/classes/fckelementpath.js' ) ; … … 101 105 LoadScript( '_source/internals/fcktablehandler_' + sSuffix + '.js' ) ; 102 106 LoadScript( '_source/classes/fckxml_' + sSuffix + '.js' ) ; 103 LoadScript( '_source/classes/fckstyledef.js' ) ;104 LoadScript( '_source/classes/fckstyledef_' + sSuffix + '.js' ) ;105 LoadScript( '_source/classes/fckstylesloader.js' ) ;106 107 107 108 LoadScript( '_source/commandclasses/fcknamedcommand.js' ) ; 109 LoadScript( '_source/commandclasses/fckstylecommand.js' ) ; 108 110 LoadScript( '_source/commandclasses/fck_othercommands.js' ) ; 109 111 LoadScript( '_source/commandclasses/fckshowblocks.js' ) ; … … 113 115 LoadScript( '_source/commandclasses/fckpastewordcommand.js' ) ; 114 116 LoadScript( '_source/commandclasses/fcktablecommand.js' ) ; 115 LoadScript( '_source/commandclasses/fckstylecommand.js' ) ;116 117 LoadScript( '_source/commandclasses/fckfitwindow.js' ) ; 117 118 LoadScript( '_source/commandclasses/fcklistcommands.js' ) ; 119 LoadScript( '_source/commandclasses/fckcorestylecommand.js' ) ; 120 LoadScript( '_source/commandclasses/fckremoveformatcommand.js' ) ; 118 121 LoadScript( '_source/internals/fckcommands.js' ) ; 119 122 … … 124 127 LoadScript( '_source/classes/fckspecialcombo.js' ) ; 125 128 LoadScript( '_source/classes/fcktoolbarspecialcombo.js' ) ; 129 LoadScript( '_source/classes/fcktoolbarstylecombo.js' ) ; 130 LoadScript( '_source/classes/fcktoolbarfontformatcombo.js' ) ; 126 131 LoadScript( '_source/classes/fcktoolbarfontscombo.js' ) ; 127 132 LoadScript( '_source/classes/fcktoolbarfontsizecombo.js' ) ; 128 LoadScript( '_source/classes/fcktoolbarfontformatcombo.js' ) ;129 LoadScript( '_source/classes/fcktoolbarstylecombo.js' ) ;130 133 LoadScript( '_source/classes/fcktoolbarpanelbutton.js' ) ; 131 134 LoadScript( '_source/internals/fcktoolbaritems.js' ) ; … … 169 172 FCK.IECleanup.AddItem( FCK, FCK_Cleanup ) ; 170 173 } 174 175 // The first function to be called on selection change must the the styles 176 // change checker, because the result of its processing may be used by another 177 // functions listening to the same event. 178 FCK.Events.AttachEvent( 'OnSelectionChange', function() { FCKStyles.CheckSelectionChanges() ; } ) ; 171 179 172 180 // The config hidden field is processed immediately, because -
FCKeditor/trunk/editor/_source/classes/fckdomrange_gecko.js
r694 r774 72 72 } 73 73 } 74 75 // Not compatible with bookmark created with CreateBookmark2. 76 // The bookmark nodes will be deleted from the document. 77 FCKDomRange.prototype.SelectBookmark = function( bookmark ) 78 { 79 var domRange = this.Window.document.createRange() ; 80 81 var startNode = this.GetBookmarkNode( bookmark, true ) ; 82 var endNode = this.GetBookmarkNode( bookmark, false ) ; 83 84 domRange.setStart( startNode.parentNode, FCKDomTools.GetIndexOf( startNode ) ) ; 85 FCKDomTools.RemoveNode( startNode ) ; 86 87 if ( endNode ) 88 { 89 domRange.setEnd( endNode.parentNode, FCKDomTools.GetIndexOf( endNode ) ) ; 90 FCKDomTools.RemoveNode( endNode ) ; 91 } 92 93 var selection = this.Window.getSelection() ; 94 selection.removeAllRanges() ; 95 selection.addRange( domRange ) ; 96 } -
FCKeditor/trunk/editor/_source/classes/fckdomrange_ie.js
r733 r774 70 70 { 71 71 if ( this._Range ) 72 {73 var bIsCollapsed = this.CheckIsCollapsed() ; 72 this.SelectBookmark( this.CreateBookmark( true ) ) ; 73 } 74 74 75 // Create marker tags for the start and end boundaries. 76 var eStartMarker = this._GetRangeMarkerTag( true ) ; 75 // Not compatible with bookmark created with CreateBookmark2. 76 // The bookmark nodes will be deleted from the document. 77 FCKDomRange.prototype.SelectBookmark = function( bookmark ) 78 { 79 var bIsCollapsed = this.CheckIsCollapsed() ; 77 80 var bIsStartMakerAlone ; 78 81 79 if ( !bIsCollapsed ) 80 var eEndMarker = this._GetRangeMarkerTag( false ) ; 82 // Create marker tags for the start and end boundaries. 83 var eStartMarker = this.GetBookmarkNode( bookmark, true ) ; 84 85 if ( !eStartMarker ) 86 return ; 81 87 82 // Create the main range which will be used for the selection. 83 var oIERange = this.Window.document.body.createTextRange() ; 88 var eEndMarker ; 89 if ( !bIsCollapsed ) 90 eEndMarker = this.GetBookmarkNode( bookmark, false ) ; 84 91 85 // Position the range at the start boundary. 86 oIERange.moveToElementText( eStartMarker ) ; 87 oIERange.moveStart( 'character', 1 ) ; 92 // Create the main range which will be used for the selection. 93 var oIERange = this.Window.document.body.createTextRange() ; 88 94 89 if ( !bIsCollapsed ) 95 // Position the range at the start boundary. 96 oIERange.moveToElementText( eStartMarker ) ; 97 oIERange.moveStart( 'character', 1 ) ; 98 99 if ( eEndMarker ) 100 { 101 // Create a tool range for the end. 102 var oIERangeEnd = this.Window.document.body.createTextRange() ; 103 104 // Position the tool range at the end. 105 oIERangeEnd.moveToElementText( eEndMarker ) ; 106 107 // Move the end boundary of the main range to match the tool range. 108 oIERange.setEndPoint( 'EndToEnd', oIERangeEnd ) ; 109 oIERange.moveEnd( 'character', -1 ) ; 110 } 111 else 112 bIsStartMakerAlone = ( !eStartMarker.previousSibling || eStartMarker.previousSibling.nodeName.toLowerCase() == 'br' ) && !eStartMarker.nextSibing ; 113 114 if ( !this._Range ) 115 this._Range = this.CreateRange() ; 116 117 // Remove the markers (reset the position, because of the changes in the DOM tree). 118 this._Range.setStartBefore( eStartMarker ) ; 119 eStartMarker.parentNode.removeChild( eStartMarker ) ; 120 121 if ( bIsCollapsed ) 122 { 123 if ( bIsStartMakerAlone ) 90 124 { 91 // Create a tool range for the end.92 var oIERangeEnd = this.Window.document.body.createTextRange() ;125 // The following trick is needed so IE makes collapsed selections 126 // inside empty blocks visible (expands the block). 93 127 94 // Position the tool range at the end. 95 oIERangeEnd.moveToElementText( eEndMarker ) ; 128 try 129 { 130 oIERange.pasteHTML( ' ' ) ; 131 132 // Move the selection start to include the . 133 oIERange.moveStart( 'character', -1 ) ; 134 } 135 catch (e){} 96 136 97 // Move the end boundary of the main range to match the tool range. 98 oIERange.setEndPoint( 'EndToEnd', oIERangeEnd ) ; 99 oIERange.moveEnd( 'character', -1 ) ; 137 // The following must be done into a separate try block. (#1034) 138 try 139 { 140 oIERange.select() ; 141 this.Window.document.selection.clear() ; 142 } 143 catch (e){} 100 144 } 101 145 else 102 bIsStartMakerAlone = ( !eStartMarker.previousSibling || eStartMarker.previousSibling.nodeName.toLowerCase() == 'br' ) && !eStartMarker.nextSibing ;103 104 // Remove the markers (reset the position, because of the changes in the DOM tree).105 this._Range.setStartBefore( eStartMarker ) ;106 eStartMarker.parentNode.removeChild( eStartMarker ) ;107 108 if ( bIsCollapsed )109 {110 if ( bIsStartMakerAlone )111 {112 // The following trick is needed so IE makes collapsed selections113 // inside empty blocks visible (expands the block).114 115 try116 {117 oIERange.pasteHTML( ' ' ) ;118 119 // Move the selection start to include the .120 oIERange.moveStart( 'character', -1 ) ;121 }122 catch (e){}123 124 // The following must be done into a separate try block. (#1034)125 try126 {127 oIERange.select() ;128 this.Window.document.selection.clear() ;129 }130 catch (e){}131 }132 else133 oIERange.select() ;134 }135 else136 {137 this._Range.setEndBefore( eEndMarker ) ;138 eEndMarker.parentNode.removeChild( eEndMarker ) ;139 146 oIERange.select() ; 140 } 147 } 148 else 149 { 150 this._Range.setEndBefore( eEndMarker ) ; 151 eEndMarker.parentNode.removeChild( eEndMarker ) ; 152 oIERange.select() ; 141 153 } 142 154 } … … 175 187 return doc.getElementById( sMarkerId ) ; 176 188 } 177 178 FCKDomRange.prototype._GetRangeMarkerTag = function( toStart )179 {180 // Get a range for the start boundary.181 var oRange = this._Range ;182 183 // insertNode() will add the node at the beginning of the Range, updating184 // the endOffset if necessary. So, we can work with the current range in this case.185 if ( !toStart )186 {187 oRange = oRange.cloneRange() ;188 oRange.collapse( toStart === true ) ;189 }190 191 var eSpan = this.Window.document.createElement( 'span' ) ;192 eSpan.innerHTML = ' ' ;193 oRange.insertNode( eSpan ) ;194 195 return eSpan ;196 } -
FCKeditor/trunk/editor/_source/classes/fckdomrange.js
r720 r774 34 34 _UpdateElementInfo : function() 35 35 { 36 if ( !this._Range ) 36 var innerRange = this._Range ; 37 38 if ( !innerRange ) 37 39 this.Release( true ) ; 38 40 else 39 41 { 40 var eStart = this._Range.startContainer ; 41 var eEnd = this._Range.endContainer ; 42 // For text nodes, the node itself is the StartNode. 43 var eStart = innerRange.startContainer ; 44 var eEnd = innerRange.endContainer ; 42 45 43 46 var oElementPath = new FCKElementPath( eStart ) ; 44 this.StartContainer = oElementPath.LastElement ; 47 this.StartNode = eStart.nodeType == 3 ? eStart : eStart.childNodes[ innerRange.startOffset ] ; 48 this.StartContainer = eStart ; 45 49 this.StartBlock = oElementPath.Block ; 46 50 this.StartBlockLimit = oElementPath.BlockLimit ; … … 48 52 if ( eStart != eEnd ) 49 53 oElementPath = new FCKElementPath( eEnd ) ; 50 this.EndContainer = oElementPath.LastElement ; 54 this.EndNode = eEnd.nodeType == 3 ? eEnd : eEnd.childNodes[ innerRange.endOffset ] ; 55 this.EndContainer = eEnd ; 51 56 this.EndBlock = oElementPath.Block ; 52 57 this.EndBlockLimit = oElementPath.BlockLimit ; … … 215 220 }, 216 221 217 CreateBookmark : function() 222 // This is an "intrusive" way to create a bookmark. It includes <span> tags 223 // in the range boundaries. The advantage of it is that it is possible to 224 // handle DOM mutations when moving back to the bookmark. 225 // Attention: the inclusion of nodes in the DOM is a design choice and 226 // should not be changes as there are other points in the code that may be 227 // using those nodes to perform operations. See GetBookmarkNode. 228 // For performance, includeNodes=true if intended to SelectBookmark. 229 CreateBookmark : function( includeNodes ) 218 230 { 219 231 // Create the bookmark info (random IDs). 220 232 var oBookmark = 221 233 { 222 StartId : 'fck_dom_range_start_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000),223 EndId : 'fck_dom_range_end_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000)234 StartId : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'S', 235 EndId : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'E' 224 236 } ; 225 237 … … 233 245 eSpan = oDoc.createElement( 'span' ) ; 234 246 eSpan.id = oBookmark.EndId ; 235 eSpan.innerHTML = ' ' ; // For IE, it must have something inside, otherwise it may be removed during operations. 247 eSpan.setAttribute( '_fck_bookmark', true ) ; 248 249 // For IE, it must have something inside, otherwise it may be 250 // removed during DOM operations. 251 // if ( FCKBrowserInfo.IsIE ) 252 eSpan.innerHTML = ' ' ; 236 253 237 254 oClone = this.Clone() ; 238 255 oClone.Collapse( false ) ; 239 256 oClone.InsertNode( eSpan ) ; 257 258 if ( includeNodes ) 259 oBookmark.EndNode = eSpan ; 240 260 } 241 261 242 262 eSpan = oDoc.createElement( 'span' ) ; 243 263 eSpan.id = oBookmark.StartId ; 244 eSpan.innerHTML = ' ' ; // For IE, it must have something inside, otherwise it may be removed during operations. 264 eSpan.setAttribute( '_fck_bookmark', true ) ; 265 266 // For IE, it must have something inside, otherwise it may be removed 267 // during DOM operations. 268 // if ( FCKBrowserInfo.IsIE ) 269 eSpan.innerHTML = ' ' ; 245 270 246 271 oClone = this.Clone() ; … … 248 273 oClone.InsertNode( eSpan ) ; 249 274 275 if ( includeNodes ) 276 oBookmark.StartNode = eSpan ; 277 250 278 return oBookmark ; 251 279 }, 252 280 281 // This one should be a part of a hypothetic "bookmark" object. 282 GetBookmarkNode : function( bookmark, start ) 283 { 284 var doc = this.Window.document ; 285 286 if ( start ) 287 return bookmark.StartNode || doc.getElementById( bookmark.StartId ) ; 288 else 289 return bookmark.EndNode || doc.getElementById( bookmark.EndId ) ; 290 }, 291 253 292 MoveToBookmark : function( bookmark, preserveBookmark ) 254 293 { 255 var oDoc = this.Window.document ; 256 257 var eStartSpan = oDoc.getElementById( bookmark.StartId ) ; 258 var eEndSpan = oDoc.getElementById( bookmark.EndId ) ; 294 var eStartSpan = this.GetBookmarkNode( bookmark, true ) ; 295 var eEndSpan = this.GetBookmarkNode( bookmark, false ) ; 259 296 260 297 this.SetStart( eStartSpan, 3 ) ; … … 263 300 FCKDomTools.RemoveNode( eStartSpan ) ; 264 301 265 // If collapsed, the startspan will not be available.302 // If collapsed, the end span will not be available. 266 303 if ( eEndSpan ) 267 304 { … … 284 321 if ( ! this._Range ) 285 322 return { "Start" : 0, "End" : 0 } ; 286 323 287 324 // First, we record down the offset values 288 var bookmark = 325 var bookmark = 289 326 { 290 327 "Start" : [ this._Range.startOffset ], … … 424 461 switch ( unit ) 425 462 { 463 // Expand the range to include all inline parent elements if we are 464 // are in their boundary limits. 465 // For example (where [ ] are the range limits): 466 // Before => Some <b>[<i>Some sample text]</i></b>. 467 // After => Some [<b><i>Some sample text</i></b>]. 468 case 'inline_elements' : 469 // Expand the start boundary. 470 if ( this._Range.startOffset == 0 ) 471 { 472 oNode = this._Range.startContainer ; 473 474 if ( oNode.nodeType != 1 ) 475 oNode = oNode.parentNode ; 476 477 while ( FCKListsLib.InlineNonEmptyElements[ oNode.nodeName.toLowerCase() ] ) 478 { 479 this._Range.setStartBefore( oNode ) ; 480 481 if ( oNode != oNode.parentNode.firstChild ) 482 break ; 483 484 oNode = oNode.parentNode ; 485 } 486 } 487 488 // Expand the end boundary. 489 oNode = this._Range.endContainer ; 490 var offset = this._Range.endOffset ; 491 492 if ( ( oNode.nodeType == 3 && offset >= oNode.nodeValue.length ) || ( oNode.nodeType == 1 && offset >= oNode.childNodes.length ) || ( oNode.nodeType != 1 && oNode.nodeType != 3 ) ) 493 { 494 if ( oNode.nodeType != 1 ) 495 oNode = oNode.parentNode ; 496 497 while ( FCKListsLib.InlineNonEmptyElements[ oNode.nodeName.toLowerCase() ] ) 498 { 499 this._Range.setEndAfter( oNode ) ; 500 501 if ( oNode != oNode.parentNode.lastChild ) 502 break ; 503 504 oNode = oNode.parentNode ; 505 } 506 } 507 508 break ; 509 426 510 case 'block_contents' : 427 511 if ( this.StartBlock ) … … 531 615 if ( !eStartBlock ) 532 616 { 533 eStartBlock = this. _FixBlock( true ) ;534 eEndBlock = this.EndBlock ; // _FixBlock may have fixed the EndBlock too.617 eStartBlock = this.FixBlock( true ) ; 618 eEndBlock = this.EndBlock ; // FixBlock may have fixed the EndBlock too. 535 619 } 536 620 537 621 if ( !eEndBlock ) 538 eEndBlock = this. _FixBlock( false ) ;622 eEndBlock = this.FixBlock( false ) ; 539 623 } 540 624 … … 546 630 this.DeleteContents() ; 547 631 548 if ( eStartBlock && eEndBlock && eStartBlock == eEndBlock )632 if ( eStartBlock && eEndBlock && eStartBlock == eEndBlock ) 549 633 { 550 634 if ( bIsStartOfBlock ) … … 596 680 597 681 // Transform a block without a block tag in a valid block (orphan text in the body or td, usually).