Ticket #3083: 3083_2.patch

File 3083_2.patch, 28.5 KB (added by Frederico Caldeira Knabben, 11 years ago)
  • _samples/enterkey.html

     
     1<!--
     2Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     3For licensing, see LICENSE.html or http://ckeditor.com/license
     4-->
     5<html xmlns="http://www.w3.org/1999/xhtml">
     6<head>
     7        <title>ENTER Key Configuration - CKEditor Sample</title>
     8        <script type="text/javascript" src="sample.js"></script>
     9        <script id="headscript" type="text/javascript">
     10        //<![CDATA[
     11
     12var editor;
     13
     14function changeEnter()
     15{
     16        // If we already have an editor, let's destroy it first.
     17        if ( editor )
     18                editor.destroy();
     19
     20        // Create the editor again, with the appropriate settings.
     21        editor = CKEDITOR.replace( 'editor1',
     22                {
     23                        enterMode               : Number( document.getElementById( 'xEnter' ).value ),
     24                        shiftEnterMode  : Number( document.getElementById( 'xShiftEnter' ).value )
     25                });
     26}
     27
     28window.onload = changeEnter;
     29
     30        //]]>
     31        </script>
     32</head>
     33<body>
     34        <!--
     35                The values in the select boxes represent the contants taht can be used
     36                to configure the enter key. You can use the constants directly instead
     37                of their numeric values:
     38                        - CKEDITOR.ENTER_P              = 1;
     39                        - CKEDITOR.ENTER_BR             = 2;
     40                        - CKEDITOR.ENTER_DIV    = 3;
     41        -->
     42        <div id="html">
     43                <div style="float: left; margin-right: 20px">
     44                        When ENTER is pressed:<br />
     45                        <select id="xEnter" onchange="changeEnter();">
     46                                <option value="1" selected="selected">Create new &lt;P&gt; (recommended)</option>
     47                                <option value="3">Create new &lt;DIV&gt;</option>
     48                                <option value="2">Break the line with a &lt;BR&gt;</option>
     49                        </select>
     50                </div>
     51                <div style="float: left">
     52                        When SHIFT + ENTER is pressed:<br />
     53                        <select id="xShiftEnter" onchange="changeEnter();">
     54                                <option value="1">Create new &lt;P&gt;</option>
     55                                <option value="3">Create new &lt;DIV&gt;</option>
     56                                <option value="2" selected="selected">Break the line with a &lt;BR&gt; (recommended)</option>
     57                        </select>
     58                </div>
     59                <br style="clear: both" />
     60                <form action="sample_posteddata.php" method="post">
     61                        <p>
     62                                <br />
     63                                <textarea id="editor1" name="editor1" rows="10" cols="80">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://www.fckeditor.net/"&gt;FCKeditor&lt;/a&gt;.&lt;/p&gt;</textarea>
     64                        </p>
     65                        <p>
     66                                <input type="submit" value="Submit" />
     67                        </p>
     68                </form>
     69        </div>
     70        <div id="code">
     71                <pre></pre>
     72        </div>
     73</body>
     74</html>
  • _source/core/config.js

     
    88 * default configuration settings.
    99 */
    1010
     11CKEDITOR.ENTER_P        = 1;
     12CKEDITOR.ENTER_BR       = 2;
     13CKEDITOR.ENTER_DIV      = 3;
     14
    1115/**
    1216 * Holds the default configuration settings. Changes to this object are
    1317 * reflected in all editor instances, if not specificaly specified for those
     
    9599         */
    96100        defaultLanguage : 'en',
    97101
    98         enterMode : 'p',
    99         shiftEnterMode : 'br',
     102        enterMode : CKEDITOR.ENTER_P,
     103        shiftEnterMode : CKEDITOR.ENTER_BR,
    100104
    101105        /**
    102106         * A comma separated list of plugins that are not related to editor
     
    147151         * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea';
    148152         */
    149153
    150         plugins : 'basicstyles,blockquote,button,clipboard,colorbutton,contextmenu,elementspath,entities,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,showblocks,sourcearea,stylescombo,table,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
     154        plugins : 'basicstyles,blockquote,button,clipboard,colorbutton,contextmenu,elementspath,enterkey,entities,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,showblocks,sourcearea,stylescombo,table,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
    151155
    152156        /**
    153157         * The theme to be used to build the UI.
  • _source/core/dom/element.js

     
    193193                append : function( node, toStart )
    194194                {
    195195                        if ( typeof node == 'string' )
    196                                 node = new CKEDITOR.dom.element( node );
     196                                node = this.getDocument().createElement( node );
    197197
    198198                        if ( toStart )
    199199                                this.$.insertBefore( node.$, this.$.firstChild );
     
    205205
    206206                appendHtml : function( html )
    207207                {
    208                         var temp = new CKEDITOR.dom.element( 'div', this.getDocument() );
    209                         temp.setHtml( html );
    210                         temp.moveChildren( this );
     208                        if ( !this.$.childNodes.length )
     209                                this.setHtml( html );
     210                        else
     211                        {
     212                                var temp = new CKEDITOR.dom.element( 'div', this.getDocument() );
     213                                temp.setHtml( html );
     214                                temp.moveChildren( this );
     215                        }
    211216                },
    212217
    213218                /**
     
    229234                                this.append( new CKEDITOR.dom.text( text ) );
    230235                },
    231236
     237                appendBogus : function()
     238                {
     239                        var lastChild = this.getLast() ;
     240
     241                        // Ignore empty/spaces text.
     242                        while ( lastChild && lastChild.type == CKEDITOR.NODE_TEXT && CKEDITOR.tools.rtrim( lastChild.getText() ).length == 0 )
     243                                lastChild = lastChild.getPrevious();
     244
     245                        if ( !lastChild || ( lastChild.is && ( !lastChild.is( 'br' ) || !lastChild.getAttribute( '_cke_bogus' ) ) ) )
     246                        {
     247                                this.append(
     248                                        CKEDITOR.env.opera ?
     249                                                this.getDocument().createText('') :
     250                                                this.getDocument().createElement( 'br', { attributes : { _cke_bogus : 1 } } ) );
     251                        }
     252                },
     253
    232254                /**
    233255                 * Breaks one of the ancestor element in the element position, moving
    234256                 * this element between the broken parts.
     
    658680                        return false;
    659681                },
    660682
     683                isEditable : function()
     684                {
     685                        // Get the element name.
     686                        var name = this.getName();
     687
     688                        // Get the element DTD (defaults to span for unknown elements).
     689                        var dtd = !CKEDITOR.dtd.$nonEditable[ name ]
     690                                                && ( CKEDITOR.dtd[ name ] || CKEDITOR.dtd.span );
     691
     692                        // In the DTD # == text node.
     693                        return ( dtd && dtd['#'] );
     694                },
     695
    661696                isIdentical : function( otherElement )
    662697                {
    663698                        if ( this.getName() != otherElement.getName() )
  • _source/core/dom/node.js

     
    9494
    9595                clone : function( includeChildren )
    9696                {
    97                         return new CKEDITOR.dom.node( this.$.cloneNode( includeChildren ) );
     97                        var $clone = this.$.cloneNode( includeChildren );
     98                       
     99                        if ( this.type == CKEDITOR.NODE_ELEMENT )
     100                        {
     101                                // The "id" attribute should never be cloned to avoid duplication.
     102                                $clone.removeAttribute( 'id', false ) ;
     103                                $clone.removeAttribute( '_cke_expando', false ) ;
     104                        }
     105                       
     106                        return new CKEDITOR.dom.node( $clone );
    98107                },
    99108
    100109                hasPrevious : function()
  • _source/core/dom/range.js

     
    10951095                                case CKEDITOR.ENLARGE_BLOCK_CONTENTS:
    10961096                                case CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:
    10971097                                        // DFS backward to get the block/list item boundary at or before the start.
    1098                                         var boundaryNodes = this.getBoundaryNodes(),
    1099                                                 startNode = boundaryNodes.startNode,
    1100                                                 endNode = boundaryNodes.endNode,
    1101                                                 guardFunction = ( unit == CKEDITOR.ENLARGE_BLOCK_CONTENTS ?
    1102                                                         CKEDITOR.dom.domWalker.blockBoundary() :
    1103                                                         CKEDITOR.dom.domWalker.listItemBoundary() ),
    1104                                                 walker = new CKEDITOR.dom.domWalker( startNode ),
    1105                                                 data = walker.reverse( guardFunction ),
    1106                                                 boundaryEvent = data.events.shift();
     1098                                       
     1099                                        // Get the boundaries nodes.
     1100                                        var startNode = this.getTouchedStartNode(),
     1101                                                endNode = this.getTouchedEndNode();
    11071102
    1108                                         this.setStartBefore( boundaryEvent.from );
     1103                                        if ( startNode.isBlockBoundary() )
     1104                                        {
     1105                                                this.setStartAt( startNode,
     1106                                                        CKEDITOR.dtd.$empty[ startNode.getName() ] ?
     1107                                                                CKEDITOR.POSITION_AFTER_END :
     1108                                                                CKEDITOR.POSITION_AFTER_START );
     1109                                        }
     1110                                        else
     1111                                        {                                       
     1112                                                // Get the function used to check the enlaarging limits.
     1113                                                var guardFunction = ( unit == CKEDITOR.ENLARGE_BLOCK_CONTENTS ?
     1114                                                                CKEDITOR.dom.domWalker.blockBoundary() :
     1115                                                                CKEDITOR.dom.domWalker.listItemBoundary() );
    11091116
    1110                                         // DFS forward to get the block/list item boundary at or before the end.
    1111                                         walker.setNode( endNode );
    1112                                         data = walker.forward( guardFunction );
    1113                                         boundaryEvent = data.events.shift();
     1117                                                // Create the DOM walker, which will traverse the DOM.
     1118                                                var walker = new CKEDITOR.dom.domWalker( startNode );
     1119                                               
     1120                                                // Go walk in reverse sense.
     1121                                                var data = walker.reverse( guardFunction );
     1122                                       
     1123                                                var boundaryEvent = data.events.shift();
    11141124
    1115                                         this.setEndAfter( boundaryEvent.from );
    1116                                         break;
     1125                                                this.setStartBefore( boundaryEvent.from );
     1126                                        }
    11171127
    1118                                 default:
     1128                                        if ( endNode.isBlockBoundary() )
     1129                                        {
     1130                                                this.setEndAt( endNode,
     1131                                                        CKEDITOR.dtd.$empty[ startNode.getName() ] ?
     1132                                                                CKEDITOR.POSITION_BEFORE_START :
     1133                                                                CKEDITOR.POSITION_BEFORE_END );
     1134                                        }
     1135                                        else
     1136                                        {                                       
     1137                                                // DFS forward to get the block/list item boundary at or before the end.
     1138                                                walker.setNode( endNode );
     1139                                                data = walker.forward( guardFunction );
     1140                                                boundaryEvent = data.events.shift();
     1141
     1142                                                this.setEndAfter( boundaryEvent.from );
     1143                                        }
    11191144                        }
    11201145                },
    11211146
     
    12811306                        updateCollapsed( this );
    12821307                },
    12831308
    1284                 // TODO: Does not add bogus <br> to empty fixed blocks.
    12851309                fixBlock : function( isStart, blockTag )
    12861310                {
    12871311                        var bookmark = this.createBookmark(),
    1288                                 fixedBlock = new CKEDITOR.dom.element( blockTag, this.document );
     1312                                fixedBlock = this.document.createElement( blockTag );
     1313
    12891314                        this.collapse( isStart );
     1315
    12901316                        this.enlarge( CKEDITOR.ENLARGE_BLOCK_CONTENTS );
     1317
    12911318                        this.extractContents().appendTo( fixedBlock );
    12921319                        fixedBlock.trim();
     1320
     1321                        if ( !CKEDITOR.env.ie )
     1322                                fixedBlock.appendBogus();
     1323
    12931324                        this.insertNode( fixedBlock );
     1325
    12941326                        this.moveToBookmark( bookmark );
     1327
    12951328                        return fixedBlock;
    12961329                },
    12971330
    12981331                splitBlock : function( blockTag )
    12991332                {
    1300                         var startPath = new CKEDITOR.dom.elementPath( this.startContainer ),
    1301                                 endPath = new CKEDITOR.dom.elementPath( this.endContainer ),
    1302                                 startBlockLimit = startPath.blockLimit,
    1303                                 endBlockLimit = endPath.blockLimit,
    1304                                 startBlock = startPath.block,
    1305                                 endBlock = endPath.block,
    1306                                 elementPath = null;
     1333                        var startPath   = new CKEDITOR.dom.elementPath( this.startContainer ),
     1334                                endPath         = new CKEDITOR.dom.elementPath( this.endContainer );
    13071335
     1336                        var startBlockLimit     = startPath.blockLimit,
     1337                                endBlockLimit   = endPath.blockLimit;
     1338
     1339                        var startBlock  = startPath.block,
     1340                                endBlock        = endPath.block;
     1341
     1342                        var elementPath = null;
     1343
     1344                        // Do nothing if the boundaries are in different block limits.
    13081345                        if ( !startBlockLimit.equals( endBlockLimit ) )
    13091346                                return null;
    13101347
     
    13141351                                if ( !startBlock )
    13151352                                {
    13161353                                        startBlock = this.fixBlock( true, blockTag );
    1317                                         endBlock = new CKEDITOR.dom.elementPath( this.endContainer );
     1354                                        endBlock = new CKEDITOR.dom.elementPath( this.endContainer ).block;
    13181355                                }
    13191356
    13201357                                if ( !endBlock )
     
    13521389
    13531390                                        // Duplicate the block element after it.
    13541391                                        endBlock = startBlock.clone( false );
    1355                                         endBlock.removeAttribute( 'id' );
    13561392
    13571393                                        // Place the extracted contents into the duplicated block.
    13581394                                        documentFragment.appendTo( endBlock );
    13591395                                        endBlock.insertAfter( startBlock );
    13601396                                        this.moveToPosition( startBlock, CKEDITOR.POSITION_AFTER_END );
    13611397
    1362                                         // TODO: Append bogus br to startBlock for Gecko
     1398                                        // In Gecko, the last child node must be a bogus <br>.
     1399                                        // Note: bogus <br> added under <ul> or <ol> would cause
     1400                                        // lists to be incorrectly rendered.
     1401                                        if ( !CKEDITOR.env.ie && !startBlock.is( 'ul', 'ol') )
     1402                                                startBlock.appendBogus() ;
    13631403                                }
    13641404                        }
    13651405
     
    14181458                        walker.forward( CKEDITOR.dom.domWalker.blockBoundary() );
    14191459
    14201460                        return !walker.checkFailed;
     1461                },
     1462
     1463                /**
     1464                 * Moves the range boundaries to the first editing point inside an
     1465                 * element. For example, in an element tree like
     1466                 * "&lt;p&gt;&lt;b&gt;&lt;i&gt;&lt;/i&gt;&lt;/b&gt; Text&lt;/p&gt;", the start editing point is
     1467                 * "&lt;p&gt;&lt;b&gt;&lt;i&gt;^&lt;/i&gt;&lt;/b&gt; Text&lt;/p&gt;" (inside &lt;i&gt;).
     1468                 * @param {CKEDITOR.dom.element} targetElement The element into which
     1469                 *              look for the editing spot.
     1470                 */
     1471                moveToElementEditStart : function( targetElement )
     1472                {
     1473                        var editableElement;
     1474
     1475                        while ( targetElement && targetElement.type == CKEDITOR.NODE_ELEMENT )
     1476                        {
     1477                                if ( targetElement.isEditable() )
     1478                                        editableElement = targetElement;
     1479                                else if ( editableElement )
     1480                                        break ;         // If we already found an editable element, stop the loop.
     1481
     1482                                targetElement = targetElement.getFirst();
     1483                        }
     1484
     1485                        if ( editableElement )
     1486                                this.moveToPosition( editableElement, CKEDITOR.POSITION_AFTER_START );
     1487                },
     1488
     1489                getTouchedStartNode : function()
     1490                {
     1491                        var container = this.startContainer ;
     1492
     1493                        if ( this.collapsed || container.type != CKEDITOR.NODE_ELEMENT )
     1494                                return container ;
     1495
     1496                        return container.getChild( this.startOffset ) || container ;
     1497                },
     1498
     1499                getTouchedEndNode : function()
     1500                {
     1501                        var container = this.endContainer ;
     1502
     1503                        if ( this.collapsed || container.type != CKEDITOR.NODE_ELEMENT )
     1504                                return container ;
     1505
     1506                        return container.getChild[ this.endOffset - 1 ] || container ;
    14211507                }
    14221508        };
    14231509})();
  • _source/core/dtd.js

     
    7979                $listItem : {dd:1,dt:1,li:1},
    8080
    8181                /**
     82                 * Elements that accept text nodes, but are not possible to edit into
     83                 * the browser.
     84                 * @type Object
     85                 * @example
     86                 */
     87                $nonEditable : {applet:1,button:1,embed:1,iframe:1,map:1,object:1,option:1,script:1,textarea:1},
     88
     89                /**
    8290                 * List of elements that can be ignored if empty, like "b" or "span".
    8391                 * @type Object
    8492                 * @example
    8593                 */
    86                 $removeEmpty : {abbr:1,acronym:1,address:1,b:1,bdo:1,big:1,cite:1,code:1,dfn:1,em:1,font:1,i:1,kbd:1,q:1,s:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1},
     94                $removeEmpty : {abbr:1,acronym:1,address:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,s:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1},
    8795
    8896                /**
    8997                 * List of elements that have tabindex set to zero by default.
  • _source/core/plugins.js

     
    1818        '_source/' +    // %REMOVE_LINE%
    1919        'plugins/', 'plugin' );
    2020
     21// PACKAGER_RENAME( CKEDITOR.plugins )
     22
    2123CKEDITOR.plugins.load = CKEDITOR.tools.override( CKEDITOR.plugins.load, function( originalLoad )
    2224        {
    2325                return function( name, callback, scope )
  • _source/plugins/enterkey/plugin.js

     
     1/*
     2Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     3For licensing, see LICENSE.html or http://ckeditor.com/license
     4*/
     5
     6(function()
     7{
     8        CKEDITOR.plugins.add( 'enterkey',
     9        {
     10                requires : [ 'keystrokes' ],
     11
     12                init : function( editor )
     13                {
     14                        var specialKeys = editor.specialKeys;
     15                        specialKeys[ 13 ] = enter;
     16                        specialKeys[ CKEDITOR.SHIFT + 13 ] = shiftEnter;
     17                }
     18        });
     19
     20        var forceMode,
     21                headerTagRegex = /^h[1-6]$/;
     22
     23        function shiftEnter( editor )
     24        {
     25                // On SHIFT+ENTER we want to enforce the mode to be respected, instead
     26                // of cloning the current block. (#77)
     27                forceMode = 1;
     28
     29                return enter( editor, editor.config.shiftEnterMode );
     30        }
     31
     32        function enter( editor, mode )
     33        {
     34                if ( !mode )
     35                        mode = editor.config.enterMode;
     36
     37                // Use setTimout so the keys get cancelled immediatelly.
     38                setTimeout( function()
     39                        {
     40                                if ( mode == CKEDITOR.ENTER_BR || editor.getSelection().getStartElement().hasAscendant( 'pre', true ) )
     41                                        enterBr( editor, mode );
     42                                else
     43                                        enterBlock( editor, mode );
     44
     45                                forceMode = 0;
     46                        }, 0 );
     47
     48                return true;
     49        }
     50
     51        function enterBlock( editor, mode, range )
     52        {
     53                // Get the range for the current selection.
     54                range = range || getRange( editor );
     55
     56                var doc = range.document;
     57
     58                // Determine the block element to be used.
     59                var blockTag = ( mode == CKEDITOR.ENTER_DIV ? 'div' : 'p' );
     60
     61                // Split the range.
     62                var splitInfo = range.splitBlock( blockTag );
     63
     64                if ( !splitInfo )
     65                        return;
     66
     67                // Get the current blocks.
     68                var previousBlock       = splitInfo.previousBlock,
     69                        nextBlock               = splitInfo.nextBlock;
     70
     71                var isStartOfBlock      = splitInfo.wasStartOfBlock,
     72                        isEndOfBlock    = splitInfo.wasEndOfBlock;
     73
     74                var node;
     75
     76                // If this is a block under a list item, split it as well. (#1647)
     77                if ( nextBlock )
     78                {
     79                        node = nextBlock.getParent();
     80                        if ( node.is( 'li' ) )
     81                        {
     82                                nextBlock.breakParent( node );
     83                                nextBlock.move( nextBlock.getNext(), true );
     84                        }
     85                }
     86                else if ( previousBlock && ( node = previousBlock.getParent() ) && node.is( 'li' ) )
     87                {
     88                        previousBlock.breakParent( node );
     89                        range.moveToElementEditStart( previousBlock.getNext() );
     90                        previousBlock.move( previousBlock.getPrevious() );
     91                }
     92
     93                // If we have both the previous and next blocks, it means that the
     94                // boundaries were on separated blocks, or none of them where on the
     95                // block limits (start/end).
     96                if ( !isStartOfBlock && !isEndOfBlock )
     97                {
     98                        // If the next block is an <li> with another list tree as the first
     99                        // child, we'll need to append a placeholder or the list item
     100                        // wouldn't be editable. (#1420)
     101                        if ( nextBlock.is( 'li' ) && ( node = nextBlock.getFirst() )
     102                                        && node.is && node.is( 'ul', 'ol') )
     103                                nextBlock.insertBefore( doc.createText( '\xa0' ), node );
     104
     105                        // Move the selection to the end block.
     106                        if ( nextBlock )
     107                                range.moveToElementEditStart( nextBlock );
     108                }
     109                else
     110                {
     111                        var newBlock;
     112
     113                        if ( previousBlock )
     114                        {
     115                                // Do not enter this block if it's a header tag, or we are in
     116                                // a Shift+Enter (#77). Create a new block element instead
     117                                // (later in the code).
     118                                if ( !forceMode && !headerTagRegex.test( previousBlock.getName() ) )
     119                                {
     120                                        // Otherwise, duplicate the previous block.
     121                                        newBlock = previousBlock.clone();
     122                                }
     123                        }
     124                        else if ( nextBlock )
     125                                newBlock = nextBlock.clone();
     126
     127                        if ( !newBlock )
     128                                newBlock = doc.createElement( blockTag );
     129
     130                        // Recreate the inline elements tree, which was available
     131                        // before hitting enter, so the same styles will be available in
     132                        // the new block.
     133                        var elementPath = splitInfo.elementPath;
     134                        if ( elementPath )
     135                        {
     136                                for ( var i = 0, len = elementPath.elements.length ; i < len ; i++ )
     137                                {
     138                                        var element = elementPath.elements[ i ];
     139
     140                                        if ( element.equals( elementPath.block ) || element.equals( elementPath.blockLimit ) )
     141                                                break;
     142
     143                                        if ( CKEDITOR.dtd.$removeEmpty[ element.getName() ] )
     144                                        {
     145                                                element = element.clone();
     146                                                newBlock.moveChildren( element );
     147                                                newBlock.append( element );
     148                                        }
     149                                }
     150                        }
     151
     152                        if ( !CKEDITOR.env.ie )
     153                                newBlock.appendBogus();
     154
     155                        range.insertNode( newBlock );
     156
     157                        // This is tricky, but to make the new block visible correctly
     158                        // we must select it.
     159                        // The previousBlock check has been included because it may be
     160                        // empty if we have fixed a block-less space (like ENTER into an
     161                        // empty table cell).
     162                        if ( CKEDITOR.env.ie && isStartOfBlock && ( !isEndOfBlock || !previousBlock.getChildCount() ) )
     163                        {
     164                                // Move the selection to the new block.
     165                                range.moveToElementEditStart( isEndOfBlock ? previousBlock : newBlock );
     166                                range.select();
     167                        }
     168
     169                        // Move the selection to the new block.
     170                        range.moveToElementEditStart( isStartOfBlock && !isEndOfBlock ? nextBlock : newBlock );
     171                }
     172
     173                if ( !CKEDITOR.env.ie )
     174                {
     175                        if ( nextBlock )
     176                        {
     177                                // If we have split the block, adds a temporary span at the
     178                                // range position and scroll relatively to it.
     179                                var tmpNode = doc.createElement( 'span' );
     180
     181                                // We need some content for Safari.
     182                                tmpNode.setHtml( '&nbsp;' );
     183
     184                                range.insertNode( tmpNode );
     185                                tmpNode.scrollIntoView();
     186                                range.deleteContents();
     187                        }
     188                        else
     189                        {
     190                                // We may use the above scroll logic for the new block case
     191                                // too, but it gives some weird result with Opera.
     192                                newBlock.scrollIntoView();
     193                        }
     194                }
     195
     196                range.select();
     197        }
     198
     199        function enterBr( editor, mode )
     200        {
     201                // Get the range for the current selection.
     202                var range = getRange( editor ),
     203                        doc = range.document;
     204
     205                // Determine the block element to be used.
     206                var blockTag = ( mode == CKEDITOR.ENTER_DIV ? 'div' : 'p' );
     207
     208                var isEndOfBlock = range.checkEndOfBlock();
     209
     210                var elementPath = new CKEDITOR.dom.elementPath( range.getBoundaryNodes().startNode );
     211
     212                var startBlock = elementPath.block,
     213                        startBlockTag = startBlock && elementPath.block.getName();
     214
     215                var isPre = false;
     216
     217                if ( !forceMode && startBlockTag == 'li' )
     218                        return enterBlock( editor, mode, range );
     219
     220                // If we are at the end of a header block.
     221                if ( !forceMode && isEndOfBlock && headerTagRegex.test( startBlockTag ) )
     222                {
     223                        // Insert a <br> after the current paragraph.
     224                        doc.createElement( 'br' ).insertAfter( startBlock );
     225
     226                        // A text node is required by Gecko only to make the cursor blink.
     227                        if ( CKEDITOR.env.gecko )
     228                                doc.createText( '' ).insertAfter( startBlock );
     229
     230                        // IE has different behaviors regarding position.
     231                        range.setStartAt( startBlock.getNext(), CKEDITOR.env.ie ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_START );
     232                }
     233                else
     234                {
     235                        var lineBreak;
     236
     237                        isPre = ( startBlockTag == 'pre' );
     238
     239                        if ( isPre )
     240                                lineBreak = doc.createText( CKEDITOR.env.ie ? '\r' : '\n' );
     241                        else
     242                                lineBreak = doc.createElement( 'br' );
     243
     244                        range.insertNode( lineBreak );
     245
     246                        // A text node is required by Gecko only to make the cursor blink.
     247                        if ( CKEDITOR.env.gecko )
     248                                doc.createText( '' ).insertAfter( lineBreak );
     249
     250                        // If we are at the end of a block, we must be sure the bogus node is available in that block.
     251                        if ( isEndOfBlock && !CKEDITOR.env.ie )
     252                                lineBreak.getParent().appendBogus();
     253
     254                        // IE has different behavior regarding position.
     255                        if ( CKEDITOR.env.ie )
     256                                range.setStartAt( lineBreak, CKEDITOR.POSITION_AFTER_END );
     257                        else
     258                                range.setStartAt( lineBreak.getNext(), CKEDITOR.POSITION_AFTER_START );
     259
     260                        // Scroll into view, for non IE.
     261                        if ( !CKEDITOR.env.ie )
     262                        {
     263                                var dummy = null;
     264
     265                                if ( CKEDITOR.env.opera )
     266                                        dummy = doc.createElement( 'span' );
     267                                else
     268                                        dummy = doc.createElement( 'br' );
     269
     270                                dummy.insertBefore( lineBreak.getNext() );
     271                                dummy.scrollIntoView();
     272                                dummy.remove();
     273                        }
     274                }
     275
     276                // This collapse guarantees the cursor will be blinking.
     277                range.collapse( true );
     278
     279                range.select( isPre );
     280        }
     281
     282        function getRange( editor )
     283        {
     284                // Get the selection ranges.
     285                var ranges = editor.getSelection().getRanges();
     286
     287                // Delete the contents of all ranges except the first one.
     288                for ( var i = ranges.length - 1 ; i > 0 ; i-- )
     289                {
     290                        ranges[ i ].deleteContents();
     291                }
     292
     293                // Return the first range.
     294                return ranges[ 0 ];
     295        }
     296})();
  • _source/plugins/keystrokes/plugin.js

     
    1515                 * @example
    1616                 */
    1717                editor.keystrokeHandler = new CKEDITOR.keystrokeHandler( editor );
     18
     19                editor.specialKeys = {};
    1820        },
    1921
    2022        init : function( editor )
     
    8486
    8587                var keyCombination = event.getKeystroke();
    8688                var command = this.keystrokes[ keyCombination ];
     89                var editor = this._.editor;
    8790
    88                 cancel = ( this._.editor.fire( 'key', { keyCode : keyCombination } ) === true );
     91                cancel = ( editor.fire( 'key', { keyCode : keyCombination } ) === true );
    8992
    9093                if ( !cancel )
    9194                {
    9295                        if ( command )
    9396                        {
    9497                                var data = { from : 'keystrokeHandler' };
    95                                 cancel = ( this._.editor.execCommand( command, data ) !== false );
     98                                cancel = ( editor.execCommand( command, data ) !== false );
    9699                        }
    97100
    98                         if ( !cancel )
    99                                 cancel = !!this.blockedKeystrokes[ keyCombination ];
     101                        if  ( !cancel )
     102                        {
     103                                var handler = editor.specialKeys[ keyCombination ],
     104                                        cancel = ( handler && handler( editor ) === true );
     105
     106                                if ( !cancel )
     107                                        cancel = !!this.blockedKeystrokes[ keyCombination ];
     108                        }
    100109                }
    101110
    102111                if ( cancel )
     
    166175        [ CKEDITOR.CTRL + 90 /*Z*/, 'undo' ],
    167176        [ CKEDITOR.CTRL + 89 /*Y*/, 'redo' ],
    168177        [ CKEDITOR.CTRL + CKEDITOR.SHIFT + 90 /*Z*/, 'redo' ],
     178
    169179        [ CKEDITOR.CTRL + 76 /*L*/, 'link' ],
     180
    170181        [ CKEDITOR.CTRL + 66 /*B*/, 'bold' ],
    171182        [ CKEDITOR.CTRL + 73 /*I*/, 'italic' ],
    172         [ CKEDITOR.CTRL + 85 /*U*/, 'underline' ],
    173         [ CKEDITOR.CTRL + CKEDITOR.ALT + 13 /*ENTER*/, 'fitWindow' ],
    174         [ CKEDITOR.SHIFT + 32 /*SPACE*/, 'nbsp' ]
     183        [ CKEDITOR.CTRL + 85 /*U*/, 'underline' ]
    175184];
  • _source/plugins/selection/plugin.js

     
    698698                        }
    699699                        else
    700700                        {
    701                                 isStartMakerAlone = ( !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) ) )
    702                                         && !startNode.hasNext();
     701// The isStartMakerAlone logic comes from V2. It guarantees that the lines
     702// will expand and that the cursor will be blinking on the right place.
     703// Actually, we are using this flag just to avoid using this hack in all
     704// situations, but just on those needed.
    703705
     706// But, in V3, somehow it is not interested on working whe hitting SHIFT+ENTER
     707// inside text. So, let's jsut leave the hack happen always.
     708
     709// I'm still leaving the code here just in case. We may find some other IE
     710// weirdness and uncommenting this stuff may be useful.
     711
     712//                              isStartMakerAlone = ( !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) ) )
     713//                                      && !startNode.hasNext();
     714
    704715                                // Append a temporary <span>&#65279;</span> before the selection.
    705716                                // This is needed to avoid IE destroying selections inside empty
    706717                                // inline elements, like <b></b> (#253).
     
    710721                                dummySpan.setHtml( '&#65279;' );        // Zero Width No-Break Space (U+FEFF). See #1359.
    711722                                dummySpan.insertBefore( startNode );
    712723
    713                                 if ( isStartMakerAlone )
    714                                 {
     724//                              if ( isStartMakerAlone )
     725//                              {
    715726                                        // To expand empty blocks or line spaces after <br>, we need
    716727                                        // instead to have any char, which will be later deleted using the
    717728                                        // selection.
    718                                         // \ufeff = Zero Width No-Break Space (U+FEFF). See #1359.
     729                                        // \ufeff = Zero Width No-Break Space (U+FEFF). (#1359)
    719730                                        this.document.createText( '\ufeff' ).insertBefore( startNode );
    720                                 }
     731//                              }
    721732                        }
    722733
    723734                        // Remove the markers (reset the position, because of the changes in the DOM tree).
     
    726737
    727738                        if ( collapsed )
    728739                        {
    729                                 if ( isStartMakerAlone )
    730                                 {
    731                                         // Move the selection start to include the temporary &#65279;.
    732                                         //ieRange.moveStart( 'character', -1 );
     740//                              if ( isStartMakerAlone )
     741//                              {
     742                                        // Move the selection start to include the temporary \ufeff.
     743                                        ieRange.moveStart( 'character', -1 );
    733744
    734745                                        ieRange.select();
    735746
    736747                                        // Remove our temporary stuff.
    737 //                                      this.document.$.selection.clear();
    738                                 }
    739                                 else
    740                                         ieRange.select();
     748                                        this.document.$.selection.clear();
     749//                              }
     750//                              else
     751//                                      ieRange.select();
    741752
    742753                                dummySpan.remove();
    743754                        }
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy