--- /dev/null
+/*\r
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net\r
+ * Copyright (C) 2003-2009 Frederico Caldeira Knabben\r
+ *\r
+ * == BEGIN LICENSE ==\r
+ *\r
+ * Licensed under the terms of any of the following licenses at your\r
+ * choice:\r
+ *\r
+ * - GNU General Public License Version 2 or later (the "GPL")\r
+ * http://www.gnu.org/licenses/gpl.html\r
+ *\r
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")\r
+ * http://www.gnu.org/licenses/lgpl.html\r
+ *\r
+ * - Mozilla Public License Version 1.1 or later (the "MPL")\r
+ * http://www.mozilla.org/MPL/MPL-1.1.html\r
+ *\r
+ * == END LICENSE ==\r
+ *\r
+ * Class for working with a selection range, much like the W3C DOM Range, but\r
+ * it is not intended to be an implementation of the W3C interface.\r
+ * (IE Implementation)\r
+ */\r
+\r
+FCKDomRange.prototype.MoveToSelection = function()\r
+{\r
+ this.Release( true ) ;\r
+\r
+ this._Range = new FCKW3CRange( this.Window.document ) ;\r
+\r
+ var oSel = this.Window.document.selection ;\r
+\r
+ if ( oSel.type != 'Control' )\r
+ {\r
+ var eMarkerStart = this._GetSelectionMarkerTag( true ) ;\r
+ var eMarkerEnd = this._GetSelectionMarkerTag( false ) ;\r
+\r
+ if ( !eMarkerStart && !eMarkerEnd )\r
+ {\r
+ this._Range.setStart( this.Window.document.body, 0 ) ;\r
+ this._UpdateElementInfo() ;\r
+ return ;\r
+ }\r
+\r
+ // Set the start boundary.\r
+ this._Range.setStart( eMarkerStart.parentNode, FCKDomTools.GetIndexOf( eMarkerStart ) ) ;\r
+ eMarkerStart.parentNode.removeChild( eMarkerStart ) ;\r
+\r
+ // Set the end boundary.\r
+ this._Range.setEnd( eMarkerEnd.parentNode, FCKDomTools.GetIndexOf( eMarkerEnd ) ) ;\r
+ eMarkerEnd.parentNode.removeChild( eMarkerEnd ) ;\r
+\r
+ this._UpdateElementInfo() ;\r
+ }\r
+ else\r
+ {\r
+ var oControl = oSel.createRange().item(0) ;\r
+\r
+ if ( oControl )\r
+ {\r
+ this._Range.setStartBefore( oControl ) ;\r
+ this._Range.setEndAfter( oControl ) ;\r
+ this._UpdateElementInfo() ;\r
+ }\r
+ }\r
+}\r
+\r
+FCKDomRange.prototype.Select = function( forceExpand )\r
+{\r
+ if ( this._Range )\r
+ this.SelectBookmark( this.CreateBookmark( true ), forceExpand ) ;\r
+}\r
+\r
+// Not compatible with bookmark created with CreateBookmark2.\r
+// The bookmark nodes will be deleted from the document.\r
+FCKDomRange.prototype.SelectBookmark = function( bookmark, forceExpand )\r
+{\r
+ var bIsCollapsed = this.CheckIsCollapsed() ;\r
+ var bIsStartMakerAlone ;\r
+ var dummySpan ;\r
+\r
+ // Create marker tags for the start and end boundaries.\r
+ var eStartMarker = this.GetBookmarkNode( bookmark, true ) ;\r
+\r
+ if ( !eStartMarker )\r
+ return ;\r
+\r
+ var eEndMarker ;\r
+ if ( !bIsCollapsed )\r
+ eEndMarker = this.GetBookmarkNode( bookmark, false ) ;\r
+\r
+ // Create the main range which will be used for the selection.\r
+ var oIERange = this.Window.document.body.createTextRange() ;\r
+\r
+ // Position the range at the start boundary.\r
+ oIERange.moveToElementText( eStartMarker ) ;\r
+ oIERange.moveStart( 'character', 1 ) ;\r
+\r
+ if ( eEndMarker )\r
+ {\r
+ // Create a tool range for the end.\r
+ var oIERangeEnd = this.Window.document.body.createTextRange() ;\r
+\r
+ // Position the tool range at the end.\r
+ oIERangeEnd.moveToElementText( eEndMarker ) ;\r
+\r
+ // Move the end boundary of the main range to match the tool range.\r
+ oIERange.setEndPoint( 'EndToEnd', oIERangeEnd ) ;\r
+ oIERange.moveEnd( 'character', -1 ) ;\r
+ }\r
+ else\r
+ {\r
+ bIsStartMakerAlone = ( forceExpand || !eStartMarker.previousSibling || eStartMarker.previousSibling.nodeName.toLowerCase() == 'br' ) && !eStartMarker.nextSibing ;\r
+\r
+ // Append a temporary <span></span> before the selection.\r
+ // This is needed to avoid IE destroying selections inside empty\r
+ // inline elements, like <b></b> (#253).\r
+ // It is also needed when placing the selection right after an inline\r
+ // element to avoid the selection moving inside of it.\r
+ dummySpan = this.Window.document.createElement( 'span' ) ;\r
+ dummySpan.innerHTML = '' ; // Zero Width No-Break Space (U+FEFF). See #1359.\r
+ eStartMarker.parentNode.insertBefore( dummySpan, eStartMarker ) ;\r
+\r
+ if ( bIsStartMakerAlone )\r
+ {\r
+ // To expand empty blocks or line spaces after <br>, we need\r
+ // instead to have any char, which will be later deleted using the\r
+ // selection.\r
+ // \ufeff = Zero Width No-Break Space (U+FEFF). See #1359.\r
+ eStartMarker.parentNode.insertBefore( this.Window.document.createTextNode( '\ufeff' ), eStartMarker ) ;\r
+ }\r
+ }\r
+\r
+ if ( !this._Range )\r
+ this._Range = this.CreateRange() ;\r
+\r
+ // Remove the markers (reset the position, because of the changes in the DOM tree).\r
+ this._Range.setStartBefore( eStartMarker ) ;\r
+ eStartMarker.parentNode.removeChild( eStartMarker ) ;\r
+\r
+ if ( bIsCollapsed )\r
+ {\r
+ if ( bIsStartMakerAlone )\r
+ {\r
+ // Move the selection start to include the temporary .\r
+ oIERange.moveStart( 'character', -1 ) ;\r
+\r
+ oIERange.select() ;\r
+\r
+ // Remove our temporary stuff.\r
+ this.Window.document.selection.clear() ;\r
+ }\r
+ else\r
+ oIERange.select() ;\r
+\r
+ FCKDomTools.RemoveNode( dummySpan ) ;\r
+ }\r
+ else\r
+ {\r
+ this._Range.setEndBefore( eEndMarker ) ;\r
+ eEndMarker.parentNode.removeChild( eEndMarker ) ;\r
+ oIERange.select() ;\r
+ }\r
+}\r
+\r
+FCKDomRange.prototype._GetSelectionMarkerTag = function( toStart )\r
+{\r
+ var doc = this.Window.document ;\r
+ var selection = doc.selection ;\r
+\r
+ // Get a range for the start boundary.\r
+ var oRange ;\r
+\r
+ // IE may throw an "unspecified error" on some cases (it happened when\r
+ // loading _samples/default.html), so try/catch.\r
+ try\r
+ {\r
+ oRange = selection.createRange() ;\r
+ }\r
+ catch (e)\r
+ {\r
+ return null ;\r
+ }\r
+\r
+ // IE might take the range object to the main window instead of inside the editor iframe window.\r
+ // This is known to happen when the editor window has not been selected before (See #933).\r
+ // We need to avoid that.\r
+ if ( oRange.parentElement().document != doc )\r
+ return null ;\r
+\r
+ oRange.collapse( toStart === true ) ;\r
+\r
+ // Paste a marker element at the collapsed range and get it from the DOM.\r
+ var sMarkerId = 'fck_dom_range_temp_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000) ;\r
+ oRange.pasteHTML( '<span id="' + sMarkerId + '"></span>' ) ;\r
+\r
+ return doc.getElementById( sMarkerId ) ;\r
+}\r