1/* 2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net 3 * Copyright (C) 2003-2007 Frederico Caldeira Knabben 4 * 5 * == BEGIN LICENSE == 6 * 7 * Licensed under the terms of any of the following licenses at your 8 * choice: 9 * 10 * - GNU General Public License Version 2 or later (the "GPL") 11 * http://www.gnu.org/licenses/gpl.html 12 * 13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 14 * http://www.gnu.org/licenses/lgpl.html 15 * 16 * - Mozilla Public License Version 1.1 or later (the "MPL") 17 * http://www.mozilla.org/MPL/MPL-1.1.html 18 * 19 * == END LICENSE == 20 * 21 * Class for working with a selection range, much like the W3C DOM Range, but 22 * it is not intented to be an implementation of the W3C interface. 23 * (IE Implementation) 24 */ 25 26FCKDomRange.prototype.MoveToSelection = function() 27{ 28 this.Release( true ) ; 29 30 this._Range = new FCKW3CRange( this.Window.document ) ; 31 32 var oSel = this.Window.document.selection ; 33 34 if ( oSel.type != 'Control' ) 35 { 36 // Set the start boundary. 37 eMarker = this._GetSelectionMarkerTag( true ) ; 38 this._Range.setStart( eMarker.parentNode, FCKDomTools.GetIndexOf( eMarker ) ) ; 39 eMarker.parentNode.removeChild( eMarker ) ; 40 41 // Set the end boundary. 42 var eMarker = this._GetSelectionMarkerTag( false ) ; 43 this._Range.setEnd( eMarker.parentNode, FCKDomTools.GetIndexOf( eMarker ) ) ; 44 eMarker.parentNode.removeChild( eMarker ) ; 45 46 this._UpdateElementInfo() ; 47 } 48 else 49 { 50 var oControl = oSel.createRange().item(0) ; 51 52 if ( oControl ) 53 { 54 this._Range.setStartBefore( oControl ) ; 55 this._Range.setEndAfter( oControl ) ; 56 this._UpdateElementInfo() ; 57 } 58 } 59} 60 61FCKDomRange.prototype.Select = function() 62{ 63 if ( this._Range ) 64 { 65 var bIsCollapsed = this.CheckIsCollapsed() ; 66 67 // Create marker tags for the start and end boundaries. 68 var eStartMarker = this._GetRangeMarkerTag( true ) ; 69 70 if ( !bIsCollapsed ) 71 var eEndMarker = this._GetRangeMarkerTag( false ) ; 72 73 // Create the main range which will be used for the selection. 74 var oIERange = this.Window.document.body.createTextRange() ; 75 76 // Position the range at the start boundary. 77 oIERange.moveToElementText( eStartMarker ) ; 78 oIERange.moveStart( 'character', 1 ) ; 79 80 if ( !bIsCollapsed ) 81 { 82 // Create a tool range for the end. 83 var oIERangeEnd = this.Window.document.body.createTextRange() ; 84 85 // Position the tool range at the end. 86 oIERangeEnd.moveToElementText( eEndMarker ) ; 87 88 // Move the end boundary of the main range to match the tool range. 89 oIERange.setEndPoint( 'EndToEnd', oIERangeEnd ) ; 90 oIERange.moveEnd( 'character', -1 ) ; 91 } 92 93 // Remove the markers (reset the position, because of the changes in the DOM tree). 94 this._Range.setStartBefore( eStartMarker ) ; 95 eStartMarker.parentNode.removeChild( eStartMarker ) ; 96 97 if ( bIsCollapsed ) 98 { 99 // The following trick is needed so IE makes collapsed selections 100 // inside empty blocks visible (expands the block). 101 try 102 { 103 oIERange.pasteHTML(' ') ; 104 oIERange.moveStart( 'character', -1 ) ; 105 } 106 catch (e){} 107 oIERange.select() ; 108 oIERange.pasteHTML('') ; 109 } 110 else 111 { 112 this._Range.setEndBefore( eEndMarker ) ; 113 eEndMarker.parentNode.removeChild( eEndMarker ) ; 114 oIERange.select() ; 115 } 116 } 117} 118 119FCKDomRange.prototype._GetSelectionMarkerTag = function( toStart ) 120{ 121 // Get a range for the start boundary. 122 var oRange = this.Window.document.selection.createRange() ; 123 oRange.collapse( toStart === true ) ; 124 125 // Paste a marker element at the collapsed range and get it from the DOM. 126 var sMarkerId = 'fck_dom_range_temp_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000) ; 127 oRange.pasteHTML( '<span id="' + sMarkerId + '"></span>' ) ; 128 return this.Window.document.getElementById( sMarkerId ) ; 129} 130 131FCKDomRange.prototype._GetRangeMarkerTag = function( toStart ) 132{ 133 // Get a range for the start boundary. 134 var oRange = this._Range ; 135 136 // insertNode() will add the node at the beginning of the Range, updating 137 // the endOffset if necessary. So, we can work with the current range in this case. 138 if ( !toStart ) 139 { 140 oRange = oRange.cloneRange() ; 141 oRange.collapse( toStart === true ) ; 142 } 143 144 var eSpan = this.Window.document.createElement( 'span' ) ; 145 eSpan.innerHTML = ' ' ; 146 oRange.insertNode( eSpan ) ; 147 148 return eSpan ; 149}