2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
\r
3 * Copyright (C) 2003-2009 Frederico Caldeira Knabben
\r
5 * == BEGIN LICENSE ==
\r
7 * Licensed under the terms of any of the following licenses at your
\r
10 * - GNU General Public License Version 2 or later (the "GPL")
\r
11 * http://www.gnu.org/licenses/gpl.html
\r
13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
\r
14 * http://www.gnu.org/licenses/lgpl.html
\r
16 * - Mozilla Public License Version 1.1 or later (the "MPL")
\r
17 * http://www.mozilla.org/MPL/MPL-1.1.html
\r
21 * Class for working with a selection range, much like the W3C DOM Range, but
\r
22 * it is not intended to be an implementation of the W3C interface.
\r
23 * (IE Implementation)
\r
26 FCKDomRange.prototype.MoveToSelection = function()
\r
28 this.Release( true ) ;
\r
30 this._Range = new FCKW3CRange( this.Window.document ) ;
\r
32 var oSel = this.Window.document.selection ;
\r
34 if ( oSel.type != 'Control' )
\r
36 var eMarkerStart = this._GetSelectionMarkerTag( true ) ;
\r
37 var eMarkerEnd = this._GetSelectionMarkerTag( false ) ;
\r
39 if ( !eMarkerStart && !eMarkerEnd )
\r
41 this._Range.setStart( this.Window.document.body, 0 ) ;
\r
42 this._UpdateElementInfo() ;
\r
46 // Set the start boundary.
\r
47 this._Range.setStart( eMarkerStart.parentNode, FCKDomTools.GetIndexOf( eMarkerStart ) ) ;
\r
48 eMarkerStart.parentNode.removeChild( eMarkerStart ) ;
\r
50 // Set the end boundary.
\r
51 this._Range.setEnd( eMarkerEnd.parentNode, FCKDomTools.GetIndexOf( eMarkerEnd ) ) ;
\r
52 eMarkerEnd.parentNode.removeChild( eMarkerEnd ) ;
\r
54 this._UpdateElementInfo() ;
\r
58 var oControl = oSel.createRange().item(0) ;
\r
62 this._Range.setStartBefore( oControl ) ;
\r
63 this._Range.setEndAfter( oControl ) ;
\r
64 this._UpdateElementInfo() ;
\r
69 FCKDomRange.prototype.Select = function( forceExpand )
\r
72 this.SelectBookmark( this.CreateBookmark( true ), forceExpand ) ;
\r
75 // Not compatible with bookmark created with CreateBookmark2.
\r
76 // The bookmark nodes will be deleted from the document.
\r
77 FCKDomRange.prototype.SelectBookmark = function( bookmark, forceExpand )
\r
79 var bIsCollapsed = this.CheckIsCollapsed() ;
\r
80 var bIsStartMakerAlone ;
\r
83 // Create marker tags for the start and end boundaries.
\r
84 var eStartMarker = this.GetBookmarkNode( bookmark, true ) ;
\r
86 if ( !eStartMarker )
\r
90 if ( !bIsCollapsed )
\r
91 eEndMarker = this.GetBookmarkNode( bookmark, false ) ;
\r
93 // Create the main range which will be used for the selection.
\r
94 var oIERange = this.Window.document.body.createTextRange() ;
\r
96 // Position the range at the start boundary.
\r
97 oIERange.moveToElementText( eStartMarker ) ;
\r
98 oIERange.moveStart( 'character', 1 ) ;
\r
102 // Create a tool range for the end.
\r
103 var oIERangeEnd = this.Window.document.body.createTextRange() ;
\r
105 // Position the tool range at the end.
\r
106 oIERangeEnd.moveToElementText( eEndMarker ) ;
\r
108 // Move the end boundary of the main range to match the tool range.
\r
109 oIERange.setEndPoint( 'EndToEnd', oIERangeEnd ) ;
\r
110 oIERange.moveEnd( 'character', -1 ) ;
\r
114 bIsStartMakerAlone = ( forceExpand || !eStartMarker.previousSibling || eStartMarker.previousSibling.nodeName.toLowerCase() == 'br' ) && !eStartMarker.nextSibing ;
\r
116 // Append a temporary <span></span> before the selection.
\r
117 // This is needed to avoid IE destroying selections inside empty
\r
118 // inline elements, like <b></b> (#253).
\r
119 // It is also needed when placing the selection right after an inline
\r
120 // element to avoid the selection moving inside of it.
\r
121 dummySpan = this.Window.document.createElement( 'span' ) ;
\r
122 dummySpan.innerHTML = '' ; // Zero Width No-Break Space (U+FEFF). See #1359.
\r
123 eStartMarker.parentNode.insertBefore( dummySpan, eStartMarker ) ;
\r
125 if ( bIsStartMakerAlone )
\r
127 // To expand empty blocks or line spaces after <br>, we need
\r
128 // instead to have any char, which will be later deleted using the
\r
130 // \ufeff = Zero Width No-Break Space (U+FEFF). See #1359.
\r
131 eStartMarker.parentNode.insertBefore( this.Window.document.createTextNode( '\ufeff' ), eStartMarker ) ;
\r
135 if ( !this._Range )
\r
136 this._Range = this.CreateRange() ;
\r
138 // Remove the markers (reset the position, because of the changes in the DOM tree).
\r
139 this._Range.setStartBefore( eStartMarker ) ;
\r
140 eStartMarker.parentNode.removeChild( eStartMarker ) ;
\r
142 if ( bIsCollapsed )
\r
144 if ( bIsStartMakerAlone )
\r
146 // Move the selection start to include the temporary .
\r
147 oIERange.moveStart( 'character', -1 ) ;
\r
149 oIERange.select() ;
\r
151 // Remove our temporary stuff.
\r
152 this.Window.document.selection.clear() ;
\r
155 oIERange.select() ;
\r
157 FCKDomTools.RemoveNode( dummySpan ) ;
\r
161 this._Range.setEndBefore( eEndMarker ) ;
\r
162 eEndMarker.parentNode.removeChild( eEndMarker ) ;
\r
163 oIERange.select() ;
\r
167 FCKDomRange.prototype._GetSelectionMarkerTag = function( toStart )
\r
169 var doc = this.Window.document ;
\r
170 var selection = doc.selection ;
\r
172 // Get a range for the start boundary.
\r
175 // IE may throw an "unspecified error" on some cases (it happened when
\r
176 // loading _samples/default.html), so try/catch.
\r
179 oRange = selection.createRange() ;
\r
186 // IE might take the range object to the main window instead of inside the editor iframe window.
\r
187 // This is known to happen when the editor window has not been selected before (See #933).
\r
188 // We need to avoid that.
\r
189 if ( oRange.parentElement().document != doc )
\r
192 oRange.collapse( toStart === true ) ;
\r
194 // Paste a marker element at the collapsed range and get it from the DOM.
\r
195 var sMarkerId = 'fck_dom_range_temp_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000) ;
\r
196 oRange.pasteHTML( '<span id="' + sMarkerId + '"></span>' ) ;
\r
198 return doc.getElementById( sMarkerId ) ;
\r