288 lines
6.6 KiB
JavaScript
288 lines
6.6 KiB
JavaScript
/*
|
|
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
|
|
* Copyright (C) 2003-2009 Frederico Caldeira Knabben
|
|
*
|
|
* == BEGIN LICENSE ==
|
|
*
|
|
* Licensed under the terms of any of the following licenses at your
|
|
* choice:
|
|
*
|
|
* - GNU General Public License Version 2 or later (the "GPL")
|
|
* http://www.gnu.org/licenses/gpl.html
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
|
|
* http://www.gnu.org/licenses/lgpl.html
|
|
*
|
|
* - Mozilla Public License Version 1.1 or later (the "MPL")
|
|
* http://www.mozilla.org/MPL/MPL-1.1.html
|
|
*
|
|
* == END LICENSE ==
|
|
*
|
|
* Active selection functions. (IE specific implementation)
|
|
*/
|
|
|
|
// Get the selection type.
|
|
FCKSelection.GetType = function()
|
|
{
|
|
// It is possible that we can still get a text range object even when type=='None' is returned by IE.
|
|
// So we'd better check the object returned by createRange() rather than by looking at the type.
|
|
try
|
|
{
|
|
var ieType = FCKSelection.GetSelection().type ;
|
|
if ( ieType == 'Control' || ieType == 'Text' )
|
|
return ieType ;
|
|
|
|
if ( this.GetSelection().createRange().parentElement )
|
|
return 'Text' ;
|
|
}
|
|
catch(e)
|
|
{
|
|
// Nothing to do, it will return None properly.
|
|
}
|
|
|
|
return 'None' ;
|
|
} ;
|
|
|
|
// Retrieves the selected element (if any), just in the case that a single
|
|
// element (object like and image or a table) is selected.
|
|
FCKSelection.GetSelectedElement = function()
|
|
{
|
|
if ( this.GetType() == 'Control' )
|
|
{
|
|
var oRange = this.GetSelection().createRange() ;
|
|
|
|
if ( oRange && oRange.item )
|
|
return this.GetSelection().createRange().item(0) ;
|
|
}
|
|
return null ;
|
|
} ;
|
|
|
|
FCKSelection.GetParentElement = function()
|
|
{
|
|
switch ( this.GetType() )
|
|
{
|
|
case 'Control' :
|
|
var el = FCKSelection.GetSelectedElement() ;
|
|
return el ? el.parentElement : null ;
|
|
|
|
case 'None' :
|
|
return null ;
|
|
|
|
default :
|
|
return this.GetSelection().createRange().parentElement() ;
|
|
}
|
|
} ;
|
|
|
|
FCKSelection.GetBoundaryParentElement = function( startBoundary )
|
|
{
|
|
switch ( this.GetType() )
|
|
{
|
|
case 'Control' :
|
|
var el = FCKSelection.GetSelectedElement() ;
|
|
return el ? el.parentElement : null ;
|
|
|
|
case 'None' :
|
|
return null ;
|
|
|
|
default :
|
|
var doc = FCK.EditorDocument ;
|
|
|
|
var range = doc.selection.createRange() ;
|
|
range.collapse( startBoundary !== false ) ;
|
|
|
|
var el = range.parentElement() ;
|
|
|
|
// It may happen that range is comming from outside "doc", so we
|
|
// must check it (#1204).
|
|
return FCKTools.GetElementDocument( el ) == doc ? el : null ;
|
|
}
|
|
} ;
|
|
|
|
FCKSelection.SelectNode = function( node )
|
|
{
|
|
FCK.Focus() ;
|
|
this.GetSelection().empty() ;
|
|
var oRange ;
|
|
try
|
|
{
|
|
// Try to select the node as a control.
|
|
oRange = FCK.EditorDocument.body.createControlRange() ;
|
|
oRange.addElement( node ) ;
|
|
}
|
|
catch(e)
|
|
{
|
|
// If failed, select it as a text range.
|
|
oRange = FCK.EditorDocument.body.createTextRange() ;
|
|
oRange.moveToElementText( node ) ;
|
|
}
|
|
|
|
oRange.select() ;
|
|
} ;
|
|
|
|
FCKSelection.Collapse = function( toStart )
|
|
{
|
|
FCK.Focus() ;
|
|
if ( this.GetType() == 'Text' )
|
|
{
|
|
var oRange = this.GetSelection().createRange() ;
|
|
oRange.collapse( toStart == null || toStart === true ) ;
|
|
oRange.select() ;
|
|
}
|
|
} ;
|
|
|
|
// The "nodeTagName" parameter must be Upper Case.
|
|
FCKSelection.HasAncestorNode = function( nodeTagName )
|
|
{
|
|
var oContainer ;
|
|
|
|
if ( this.GetSelection().type == "Control" )
|
|
{
|
|
oContainer = this.GetSelectedElement() ;
|
|
}
|
|
else
|
|
{
|
|
var oRange = this.GetSelection().createRange() ;
|
|
oContainer = oRange.parentElement() ;
|
|
}
|
|
|
|
while ( oContainer )
|
|
{
|
|
if ( oContainer.nodeName.IEquals( nodeTagName ) ) return true ;
|
|
oContainer = oContainer.parentNode ;
|
|
}
|
|
|
|
return false ;
|
|
} ;
|
|
|
|
// The "nodeTagName" parameter must be UPPER CASE.
|
|
// It can be also an array of names
|
|
FCKSelection.MoveToAncestorNode = function( nodeTagName )
|
|
{
|
|
var oNode, oRange ;
|
|
|
|
if ( ! FCK.EditorDocument )
|
|
return null ;
|
|
|
|
if ( this.GetSelection().type == "Control" )
|
|
{
|
|
oRange = this.GetSelection().createRange() ;
|
|
for ( i = 0 ; i < oRange.length ; i++ )
|
|
{
|
|
if (oRange(i).parentNode)
|
|
{
|
|
oNode = oRange(i).parentNode ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
oRange = this.GetSelection().createRange() ;
|
|
oNode = oRange.parentElement() ;
|
|
}
|
|
|
|
while ( oNode && !oNode.nodeName.Equals( nodeTagName ) )
|
|
oNode = oNode.parentNode ;
|
|
|
|
return oNode ;
|
|
} ;
|
|
|
|
FCKSelection.Delete = function()
|
|
{
|
|
// Gets the actual selection.
|
|
var oSel = this.GetSelection() ;
|
|
|
|
// Deletes the actual selection contents.
|
|
if ( oSel.type.toLowerCase() != "none" )
|
|
{
|
|
oSel.clear() ;
|
|
}
|
|
|
|
return oSel ;
|
|
} ;
|
|
|
|
/**
|
|
* Returns the native selection object.
|
|
*/
|
|
FCKSelection.GetSelection = function()
|
|
{
|
|
this.Restore() ;
|
|
return FCK.EditorDocument.selection ;
|
|
}
|
|
|
|
FCKSelection.Save = function( lock )
|
|
{
|
|
var editorDocument = FCK.EditorDocument ;
|
|
|
|
if ( !editorDocument )
|
|
return ;
|
|
|
|
// Avoid saving again a selection while a dialog is open #2616
|
|
if ( this.locked )
|
|
return ;
|
|
this.locked = !!lock ;
|
|
|
|
var selection = editorDocument.selection ;
|
|
var range ;
|
|
|
|
if ( selection )
|
|
{
|
|
// The call might fail if the document doesn't have the focus (#1801),
|
|
// but we don't want to modify the current selection (#2495) with a call to FCK.Focus() ;
|
|
try {
|
|
range = selection.createRange() ;
|
|
}
|
|
catch(e) {}
|
|
|
|
// Ensure that the range comes from the editor document.
|
|
if ( range )
|
|
{
|
|
if ( range.parentElement && FCKTools.GetElementDocument( range.parentElement() ) != editorDocument )
|
|
range = null ;
|
|
else if ( range.item && FCKTools.GetElementDocument( range.item(0) )!= editorDocument )
|
|
range = null ;
|
|
}
|
|
}
|
|
|
|
this.SelectionData = range ;
|
|
}
|
|
|
|
FCKSelection._GetSelectionDocument = function( selection )
|
|
{
|
|
var range = selection.createRange() ;
|
|
if ( !range )
|
|
return null;
|
|
else if ( range.item )
|
|
return FCKTools.GetElementDocument( range.item( 0 ) ) ;
|
|
else
|
|
return FCKTools.GetElementDocument( range.parentElement() ) ;
|
|
}
|
|
|
|
FCKSelection.Restore = function()
|
|
{
|
|
if ( this.SelectionData )
|
|
{
|
|
FCK.IsSelectionChangeLocked = true ;
|
|
|
|
try
|
|
{
|
|
// Don't repeat the restore process if the editor document is already selected.
|
|
if ( String( this._GetSelectionDocument( FCK.EditorDocument.selection ).body.contentEditable ) == 'true' )
|
|
{
|
|
FCK.IsSelectionChangeLocked = false ;
|
|
return ;
|
|
}
|
|
this.SelectionData.select() ;
|
|
}
|
|
catch ( e ) {}
|
|
|
|
FCK.IsSelectionChangeLocked = false ;
|
|
}
|
|
}
|
|
|
|
FCKSelection.Release = function()
|
|
{
|
|
this.locked = false ;
|
|
delete this.SelectionData ;
|
|
}
|