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 * Active selection functions. (Gecko specific implementation)
\r
24 // Get the selection type (like document.select.type in IE).
\r
25 FCKSelection.GetType = function()
\r
27 // By default set the type to "Text".
\r
30 // Check if the actual selection is a Control (IMG, TABLE, HR, etc...).
\r
33 try { sel = this.GetSelection() ; } catch (e) {}
\r
35 if ( sel && sel.rangeCount == 1 )
\r
37 var range = sel.getRangeAt(0) ;
\r
38 if ( range.startContainer == range.endContainer
\r
39 && ( range.endOffset - range.startOffset ) == 1
\r
40 && range.startContainer.nodeType == 1
\r
41 && FCKListsLib.StyleObjectElements[ range.startContainer.childNodes[ range.startOffset ].nodeName.toLowerCase() ] )
\r
50 // Retrieves the selected element (if any), just in the case that a single
\r
51 // element (object like and image or a table) is selected.
\r
52 FCKSelection.GetSelectedElement = function()
\r
54 var selection = !!FCK.EditorWindow && this.GetSelection() ;
\r
55 if ( !selection || selection.rangeCount < 1 )
\r
58 var range = selection.getRangeAt( 0 ) ;
\r
59 if ( range.startContainer != range.endContainer || range.startContainer.nodeType != 1 || range.startOffset != range.endOffset - 1 )
\r
62 var node = range.startContainer.childNodes[ range.startOffset ] ;
\r
63 if ( node.nodeType != 1 )
\r
69 FCKSelection.GetParentElement = function()
\r
71 if ( this.GetType() == 'Control' )
\r
72 return FCKSelection.GetSelectedElement().parentNode ;
\r
75 var oSel = this.GetSelection() ;
\r
78 // if anchorNode == focusNode, see if the selection is text only or including nodes.
\r
79 // if text only, return the parent node.
\r
80 // if the selection includes DOM nodes, then the anchorNode is the nearest container.
\r
81 if ( oSel.anchorNode && oSel.anchorNode == oSel.focusNode )
\r
83 var oRange = oSel.getRangeAt( 0 ) ;
\r
84 if ( oRange.collapsed || oRange.startContainer.nodeType == 3 )
\r
85 return oSel.anchorNode.parentNode ;
\r
87 return oSel.anchorNode ;
\r
90 // looks like we're having a large selection here. To make the behavior same as IE's TextRange.parentElement(),
\r
91 // we need to find the nearest ancestor node which encapsulates both the beginning and the end of the selection.
\r
92 // TODO: A simpler logic can be found.
\r
93 var anchorPath = new FCKElementPath( oSel.anchorNode ) ;
\r
94 var focusPath = new FCKElementPath( oSel.focusNode ) ;
\r
95 var deepPath = null ;
\r
96 var shallowPath = null ;
\r
97 if ( anchorPath.Elements.length > focusPath.Elements.length )
\r
99 deepPath = anchorPath.Elements ;
\r
100 shallowPath = focusPath.Elements ;
\r
104 deepPath = focusPath.Elements ;
\r
105 shallowPath = anchorPath.Elements ;
\r
108 var deepPathBase = deepPath.length - shallowPath.length ;
\r
109 for( var i = 0 ; i < shallowPath.length ; i++)
\r
111 if ( deepPath[deepPathBase + i] == shallowPath[i])
\r
112 return shallowPath[i];
\r
120 FCKSelection.GetBoundaryParentElement = function( startBoundary )
\r
122 if ( ! FCK.EditorWindow )
\r
124 if ( this.GetType() == 'Control' )
\r
125 return FCKSelection.GetSelectedElement().parentNode ;
\r
128 var oSel = this.GetSelection() ;
\r
129 if ( oSel && oSel.rangeCount > 0 )
\r
131 var range = oSel.getRangeAt( startBoundary ? 0 : ( oSel.rangeCount - 1 ) ) ;
\r
133 var element = startBoundary ? range.startContainer : range.endContainer ;
\r
135 return ( element.nodeType == 1 ? element : element.parentNode ) ;
\r
141 FCKSelection.SelectNode = function( element )
\r
143 var oRange = FCK.EditorDocument.createRange() ;
\r
144 oRange.selectNode( element ) ;
\r
146 var oSel = this.GetSelection() ;
\r
147 oSel.removeAllRanges() ;
\r
148 oSel.addRange( oRange ) ;
\r
151 FCKSelection.Collapse = function( toStart )
\r
153 var oSel = this.GetSelection() ;
\r
155 if ( toStart == null || toStart === true )
\r
156 oSel.collapseToStart() ;
\r
158 oSel.collapseToEnd() ;
\r
161 // The "nodeTagName" parameter must be Upper Case.
\r
162 FCKSelection.HasAncestorNode = function( nodeTagName )
\r
164 var oContainer = this.GetSelectedElement() ;
\r
165 if ( ! oContainer && FCK.EditorWindow )
\r
167 try { oContainer = this.GetSelection().getRangeAt(0).startContainer ; }
\r
171 while ( oContainer )
\r
173 if ( oContainer.nodeType == 1 && oContainer.nodeName.IEquals( nodeTagName ) ) return true ;
\r
174 oContainer = oContainer.parentNode ;
\r
180 // The "nodeTagName" parameter must be Upper Case.
\r
181 FCKSelection.MoveToAncestorNode = function( nodeTagName )
\r
185 var oContainer = this.GetSelectedElement() ;
\r
186 if ( ! oContainer )
\r
187 oContainer = this.GetSelection().getRangeAt(0).startContainer ;
\r
189 while ( oContainer )
\r
191 if ( oContainer.nodeName.IEquals( nodeTagName ) )
\r
192 return oContainer ;
\r
194 oContainer = oContainer.parentNode ;
\r
199 FCKSelection.Delete = function()
\r
201 // Gets the actual selection.
\r
202 var oSel = this.GetSelection() ;
\r
204 // Deletes the actual selection contents.
\r
205 for ( var i = 0 ; i < oSel.rangeCount ; i++ )
\r
207 oSel.getRangeAt(i).deleteContents() ;
\r
214 * Returns the native selection object.
\r
216 FCKSelection.GetSelection = function()
\r
218 return FCK.EditorWindow.getSelection() ;
\r
221 // The following are IE only features (we don't need then in other browsers
\r
223 FCKSelection.Save = function()
\r
225 FCKSelection.Restore = function()
\r
227 FCKSelection.Release = function()
\r