Вход Регистрация
Файл: fckeditor/editor/_source/internals/fck_gecko.js
Строк: 744
<?php

/*
 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
 * Copyright (C) 2003-2008 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 ==
 *
 * Creation and initialization of the "FCK" object. This is the main
 * object that represents an editor instance.
 * (Gecko specific implementations)
 */

FCK.Description "FCKeditor for Gecko Browsers" ;

FCK.InitializeBehaviors = function()
{
    
// When calling "SetData", the editing area IFRAME gets a fixed height. So we must recalculate it.
    
if ( window.onresize )        // Not for Safari/Opera.
        
window.onresize() ;

    
FCKFocusManager.AddWindowthis.EditorWindow ) ;

    
this.ExecOnSelectionChange = function()
    {
        
FCK.Events.FireEvent"OnSelectionChange" ) ;
    }

    
this._ExecDrop = function( evt )
    {
        if ( 
FCK.MouseDownFlag )
        {
            
FCK.MouseDownFlag false ;
            return ;
        }

        if ( 
FCKConfig.ForcePasteAsPlainText )
        {
            if ( 
evt.dataTransfer )
            {
                var 
text evt.dataTransfer.getData'Text' ) ;
                
text FCKTools.HTMLEncodetext ) ;
                
text FCKTools.ProcessLineBreakswindowFCKConfigtext ) ;
                
FCK.InsertHtmltext ) ;
            }
            else if ( 
FCKConfig.ShowDropDialog )
                
FCK.PasteAsPlainText() ;

            
evt.preventDefault() ;
            
evt.stopPropagation() ;
        }
    }

    
this._ExecCheckCaret = function( evt )
    {
        if ( 
FCK.EditMode != FCK_EDITMODE_WYSIWYG )
            return ;

        if ( 
evt.type == 'keypress' )
        {
            var 
keyCode evt.keyCode ;
            
// ignore if positioning key is not pressed.
            // left or up arrow keys need to be processed as well, since <a> links can be expanded in Gecko's editor
            // when the caret moved left or up from another block element below.
            
if ( keyCode 33 || keyCode 40 )
                return ;
        }

        var 
blockEmptyStop = function( node )
        {
            if ( 
node.nodeType != )
                return 
false ;
            var 
tag node.tagName.toLowerCase() ;
            return ( 
FCKListsLib.BlockElements[tag] || FCKListsLib.EmptyElements[tag] ) ;
        }

        var 
moveCursor = function()
        {
            var 
selection FCKSelection.GetSelection() ;
            var 
range selection.getRangeAt(0) ;
            if ( ! 
range || ! range.collapsed )
                return ;

            var 
node range.endContainer ;

            
// only perform the patched behavior if we're at the end of a text node.
            
if ( node.nodeType != )
                return ;

            if ( 
node.nodeValue.length != range.endOffset )
                return ;

            
// only perform the patched behavior if we're in an <a> tag, or the End key is pressed.
            
var parentTag node.parentNode.tagName.toLowerCase() ;
            if ( ! (  
parentTag == 'a' || ( !FCKBrowserInfo.IsOpera && String(node.parentNode.contentEditable) == 'false' ) ||
                    ( ! ( 
FCKListsLib.BlockElements[parentTag] || FCKListsLib.NonEmptyBlockElements[parentTag] )
                      && 
keyCode == 35 ) ) )
                return ;

            
// our caret has moved to just after the last character of a text node under an unknown tag, how to proceed?
            // first, see if there are other text nodes by DFS walking from this text node.
            //     - if the DFS has scanned all nodes under my parent, then go the next step.
            //    - if there is a text node after me but still under my parent, then do nothing and return.
            
var nextTextNode FCKTools.GetNextTextNodenodenode.parentNodeblockEmptyStop ) ;
            if ( 
nextTextNode )
                return ;

            
// we're pretty sure we need to move the caret forcefully from here.
            
range FCK.EditorDocument.createRange() ;

            
nextTextNode FCKTools.GetNextTextNodenodenode.parentNode.parentNodeblockEmptyStop ) ;
            if ( 
nextTextNode )
            {
                
// Opera thinks the dummy empty text node we append beyond the end of <a> nodes occupies a caret
                // position. So if the user presses the left key and we reset the caret position here, the user
                // wouldn't be able to go back.
                
if ( FCKBrowserInfo.IsOpera && keyCode == 37 )
                    return ;

                
// now we want to get out of our current parent node, adopt the next parent, and move the caret to
                // the appropriate text node under our new parent.
                // our new parent might be our current parent's siblings if we are lucky.
                
range.setStartnextTextNode) ;
                
range.setEndnextTextNode) ;
            }
            else
            {
                
// no suitable next siblings under our grandparent! what to do next?
                
while ( node.parentNode
                    
&& node.parentNode != FCK.EditorDocument.body
                    
&& node.parentNode != FCK.EditorDocument.documentElement
                    
&& node == node.parentNode.lastChild
                    
&& ( ! FCKListsLib.BlockElements[node.parentNode.tagName.toLowerCase()]
                      && ! 
FCKListsLib.NonEmptyBlockElements[node.parentNode.tagName.toLowerCase()] ) )
                    
node node.parentNode ;


                if ( 
FCKListsLib.BlockElementsparentTag ]
                        || 
FCKListsLib.EmptyElementsparentTag ]
                        || 
node == FCK.EditorDocument.body )
                {
                    
// if our parent is a block node, move to the end of our parent.
                    
range.setStartnodenode.childNodes.length ) ;
                    
range.setEndnodenode.childNodes.length ) ;
                }
                else
                {
                    
// things are a little bit more interesting if our parent is not a block node
                    // due to the weired ways how Gecko's caret acts...
                    
var stopNode node.nextSibling ;

                    
// find out the next block/empty element at our grandparent, we'll
                    // move the caret just before it.
                    
while ( stopNode )
                    {
                        if ( 
stopNode.nodeType != )
                        {
                            
stopNode stopNode.nextSibling ;
                            continue ;
                        }

                        var 
stopTag stopNode.tagName.toLowerCase() ;
                        if ( 
FCKListsLib.BlockElements[stopTag] || FCKListsLib.EmptyElements[stopTag]
                            || 
FCKListsLib.NonEmptyBlockElements[stopTag] )
                            break ;
                        
stopNode stopNode.nextSibling ;
                    }

                    
// note that the dummy marker below is NEEDED, otherwise the caret's behavior will
                    // be broken in Gecko.
                    
var marker FCK.EditorDocument.createTextNode'' ) ;
                    if ( 
stopNode )
                        
node.parentNode.insertBeforemarkerstopNode ) ;
                    else
                        
node.parentNode.appendChildmarker ) ;
                    
range.setStartmarker) ;
                    
range.setEndmarker) ;
                }
            }

            
selection.removeAllRanges() ;
            
selection.addRangerange ) ;
            
FCK.Events.FireEvent"OnSelectionChange" ) ;
        }

        
setTimeoutmoveCursor) ;
    }

    
this.ExecOnSelectionChangeTimer = function()
    {
        if ( 
FCK.LastOnChangeTimer )
            
window.clearTimeoutFCK.LastOnChangeTimer ) ;

        
FCK.LastOnChangeTimer window.setTimeoutFCK.ExecOnSelectionChange100 ) ;
    }

    
this.EditorDocument.addEventListener'mouseup'this.ExecOnSelectionChangefalse ) ;

    
// On Gecko, firing the "OnSelectionChange" event on every key press started to be too much
    // slow. So, a timer has been implemented to solve performance issues when typing to quickly.
    
this.EditorDocument.addEventListener'keyup'this.ExecOnSelectionChangeTimerfalse ) ;

    
this._DblClickListener = function( )
    {
        
FCK.OnDoubleClicke.target ) ;
        
e.stopPropagation() ;
    }
    
this.EditorDocument.addEventListener'dblclick'this._DblClickListenertrue ) ;

    
// Record changes for the undo system when there are key down events.
    
this.EditorDocument.addEventListener'keydown'this._KeyDownListenerfalse ) ;

    
// Hooks for data object drops
    
if ( FCKBrowserInfo.IsGecko )
    {
        
this.EditorWindow.addEventListener'dragdrop'this._ExecDroptrue ) ;
    }
    else if ( 
FCKBrowserInfo.IsSafari )
    {
        var 
cancelHandler = function( evt ){ if ( ! FCK.MouseDownFlag evt.returnValue false ; }
        
this.EditorDocument.addEventListener'dragenter'cancelHandlertrue ) ;
        
this.EditorDocument.addEventListener'dragover'cancelHandlertrue ) ;
        
this.EditorDocument.addEventListener'drop'this._ExecDroptrue ) ;
        
this.EditorDocument.addEventListener'mousedown',
            function( 
ev )
            {
                var 
element ev.srcElement ;

                if ( 
element.nodeName.IEquals'IMG''HR''INPUT''TEXTAREA''SELECT' ) )
                {
                    
FCKSelection.SelectNodeelement ) ;
                }
            }, 
true ) ;

        
this.EditorDocument.addEventListener'mouseup',
            function( 
ev )
            {
                if ( 
ev.srcElement.nodeName.IEquals'INPUT''TEXTAREA''SELECT' ) )
                    
ev.preventDefault()
            }, 
true ) ;

        
this.EditorDocument.addEventListener'click',
            function( 
ev )
            {
                if ( 
ev.srcElement.nodeName.IEquals'INPUT''TEXTAREA''SELECT' ) )
                    
ev.preventDefault()
            }, 
true ) ;
    }

    
// Kludge for buggy Gecko caret positioning logic (Bug #393 and #1056)
    
if ( FCKBrowserInfo.IsGecko || FCKBrowserInfo.IsOpera )
    {
        
this.EditorDocument.addEventListener'keypress'this._ExecCheckCaretfalse ) ;
        
this.EditorDocument.addEventListener'click'this._ExecCheckCaretfalse ) ;
    }

    
// Reset the context menu.
    
FCK.ContextMenu._InnerContextMenu.SetMouseClickWindowFCK.EditorWindow ) ;
    
FCK.ContextMenu._InnerContextMenu.AttachToElementFCK.EditorDocument ) ;
}

FCK.MakeEditable = function()
{
    
this.EditingArea.MakeEditable() ;
}

// Disable the context menu in the editor (outside the editing area).
function Document_OnContextMenu)
{
    if ( !
e.target._FCKShowContextMenu )
        
e.preventDefault() ;
}
document.oncontextmenu Document_OnContextMenu ;

// GetNamedCommandState overload for Gecko.
FCK._BaseGetNamedCommandState FCK.GetNamedCommandState ;
FCK.GetNamedCommandState = function( commandName )
{
    switch ( 
commandName )
    {
        case 
'Unlink' :
            return 
FCKSelection.HasAncestorNode('A') ? FCK_TRISTATE_OFF FCK_TRISTATE_DISABLED ;
        default :
            return 
FCK._BaseGetNamedCommandStatecommandName ) ;
    }
}

// Named commands to be handled by this browsers specific implementation.
FCK.RedirectNamedCommands =
{
    Print    : 
true,
    
Paste    true
} ;

// ExecuteNamedCommand overload for Gecko.
FCK.ExecuteRedirectedNamedCommand = function( commandNamecommandParameter )
{
    switch ( 
commandName )
    {
        case 
'Print' :
            
FCK.EditorWindow.print() ;
            break ;
        case 
'Paste' :
            try
            {
                
// Force the paste dialog for Safari (#50).
                
if ( FCKBrowserInfo.IsSafari )
                    throw 
'' ;

                if ( 
FCK.Paste() )
                    
FCK.ExecuteNamedCommand'Paste'nulltrue ) ;
            }
            catch (
e)    { FCKDialog.OpenDialog'FCKDialog_Paste'FCKLang.Paste'dialog/fck_paste.html'400330'Security' ) ; }
            break ;
        default :
            
FCK.ExecuteNamedCommandcommandNamecommandParameter ) ;
    }
}

FCK._ExecPaste = function()
{
    
// Save a snapshot for undo before actually paste the text
    
FCKUndo.SaveUndoStep() ;

    if ( 
FCKConfig.ForcePasteAsPlainText )
    {
        
FCK.PasteAsPlainText() ;
        return 
false ;
    }

    
/* For now, the AutoDetectPasteFromWord feature is IE only. */
    
return true ;
}

//**
// FCK.InsertHtml: Inserts HTML at the current cursor location. Deletes the
// selected content if any.
FCK.InsertHtml = function( html )
{
    var 
doc FCK.EditorDocument,
        
range;

    
html FCKConfig.ProtectedSource.Protecthtml ) ;
    
html FCK.ProtectEventshtml ) ;
    
html FCK.ProtectUrlshtml ) ;
    
html FCK.ProtectTagshtml ) ;

    
// Save an undo snapshot first.
    
FCKUndo.SaveUndoStep() ;

    if ( 
FCKBrowserInfo.IsGecko )
    {
        
html html.replace( /&nbsp;$/, '$&<span _fcktemp="1"/>' ) ;

        var 
docFrag = new FCKDocumentFragmentthis.EditorDocument ) ;
        
docFrag.AppendHtmlhtml ) ;

        var 
lastNode docFrag.RootNode.lastChild ;

        
range = new FCKDomRangethis.EditorWindow ) ;
        
range.MoveToSelection() ;
        
range.DeleteContents() ;
        
range.InsertNodedocFrag.RootNode ) ;

        
range.MoveToPositionlastNode) ;
    }
    else
        
doc.execCommand'inserthtml'falsehtml ) ;

    
this.Focus() ;

    
// Save the caret position before calling document processor.
    
if ( !range )
    {
        
range = new FCKDomRangethis.EditorWindow ) ;
        
range.MoveToSelection() ;
    }
    var 
bookmark range.CreateBookmark() ;

    
FCKDocumentProcessor.Processdoc ) ;

    
// Restore caret position, ignore any errors in case the document
    // processor removed the bookmark <span>s for some reason.
    
try
    {
        
range.MoveToBookmarkbookmark ) ;
        
range.Select() ;
    }
    catch ( 
) {}

    
// For some strange reason the SaveUndoStep() call doesn't activate the undo button at the first InsertHtml() call.
    
this.Events.FireEvent"OnSelectionChange" ) ;
}

FCK.PasteAsPlainText = function()
{
    
// TODO: Implement the "Paste as Plain Text" code.

    // If the function is called immediately Firefox 2 does automatically paste the contents as soon as the new dialog is created
    // so we run it in a Timeout and the paste event can be cancelled
    
FCKTools.RunFunctionFCKDialog.OpenDialogFCKDialog, ['FCKDialog_Paste'FCKLang.PasteAsText'dialog/fck_paste.html'400330'PlainText'] ) ;

/*
    var sText = FCKTools.HTMLEncode( clipboardData.getData("Text") ) ;
    sText = sText.replace( /n/g, '<BR>' ) ;
    this.InsertHtml( sText ) ;
*/
}
/*
FCK.PasteFromWord = function()
{
    // TODO: Implement the "Paste as Plain Text" code.

    FCKDialog.OpenDialog( 'FCKDialog_Paste', FCKLang.PasteFromWord, 'dialog/fck_paste.html', 400, 330, 'Word' ) ;

//    FCK.CleanAndPaste( FCK.GetClipboardHTML() ) ;
}
*/
FCK.GetClipboardHTML = function()
{
    return 
'' ;
}

FCK.CreateLink = function( urlnoUndo )
{
    
// Creates the array that will be returned. It contains one or more created links (see #220).
    
var aCreatedLinks = new Array() ;

    
// Only for Safari, a collapsed selection may create a link. All other
    // browser will have no links created. So, we check it here and return
    // immediatelly, having the same cross browser behavior.
    
if ( FCKSelection.GetSelection().isCollapsed )
        return 
aCreatedLinks ;

    
FCK.ExecuteNamedCommand'Unlink'nullfalse, !!noUndo ) ;

    if ( 
url.length )
    {
        
// Generate a temporary name for the link.
        
var sTempUrl 'javascript:void(0);/*' + ( new Date().getTime() ) + '*/' ;

        
// Use the internal "CreateLink" command to create the link.
        
FCK.ExecuteNamedCommand'CreateLink'sTempUrlfalse, !!noUndo ) ;

        
// Retrieve the just created links using XPath.
        
var oLinksInteractor this.EditorDocument.evaluate("//a[@href='" sTempUrl "']"this.EditorDocument.bodynullXPathResult.UNORDERED_NODE_SNAPSHOT_TYPEnull) ;

        
// Add all links to the returning array.
        
for ( var oLinksInteractor.snapshotLength i++ )
        {
            var 
oLink oLinksInteractor.snapshotItem) ;
            
oLink.href url ;

            
aCreatedLinks.pushoLink ) ;
        }
    }

    return 
aCreatedLinks ;
}

FCK._FillEmptyBlock = function( emptyBlockNode )
{
    if ( ! 
emptyBlockNode || emptyBlockNode.nodeType != )
        return ;
    var 
nodeTag emptyBlockNode.tagName.toLowerCase() ;
    if ( 
nodeTag != 'p' && nodeTag != 'div' )
        return ;
    if ( 
emptyBlockNode.firstChild )
        return ;
    
FCKTools.AppendBogusBremptyBlockNode ) ;
}

FCK._ExecCheckEmptyBlock = function()
{
    
FCK._FillEmptyBlockFCK.EditorDocument.body.firstChild ) ;
    var 
sel FCKSelection.GetSelection() ;
    if ( !
sel || sel.rangeCount )
        return ;
    var 
range sel.getRangeAt);
    
FCK._FillEmptyBlockrange.startContainer ) ;
}
?>
Онлайн: 3
Реклама