Ticket #1272: 1272_6.patch

File 1272_6.patch, 10.4 KB (added by Frederico Caldeira Knabben, 10 years ago)
  • _source/core/dom/node.js

     
    182182                },
    183183
    184184                /**
     185                 * Gets the document containing this element.
     186                 * @returns {CKEDITOR.dom.document} The document.
     187                 * @example
     188                 * var element = CKEDITOR.document.getById( 'example' );
     189                 * alert( <b>element.getDocument().equals( CKEDITOR.document )</b> );  // "true"
     190                 */
     191                getDocument : function()
     192                {
     193                        return new CKEDITOR.dom.document( this.$.ownerDocument || this.$.parentNode.ownerDocument );
     194                },
     195
     196                /**
    185197                 * Retrieves a uniquely identifiable tree address for this node.
    186198                 * The tree address returns is an array of integers, with each integer
    187199                 * indicating a child index of a DOM node, starting from
     
    204216                        while ( node && node != $documentElement )
    205217                        {
    206218                                var parentNode = node.parentNode;
    207                                 var currentIndex = -1;
    208219
    209220                                if ( parentNode )
    210221                                {
    211                                         for ( var i = 0 ; i < parentNode.childNodes.length ; i++ )
    212                                         {
    213                                                 var candidate = parentNode.childNodes[i];
    214 
    215                                                 if ( normalized &&
    216                                                                 candidate.nodeType == 3 &&
    217                                                                 candidate.previousSibling &&
    218                                                                 candidate.previousSibling.nodeType == 3 )
    219                                                 {
    220                                                         continue;
    221                                                 }
    222 
    223                                                 currentIndex++;
    224 
    225                                                 if ( candidate == node )
    226                                                         break;
    227                                         }
    228 
    229                                         address.unshift( currentIndex );
     222                                        // Get the node index. For performance, call getIndex
     223                                        // directly, instead of creating a new node object.
     224                                        address.unshift( this.getIndex.call( { $ : node }, normalized ) );
    230225                                }
    231226
    232227                                node = parentNode;
     
    235230                        return address;
    236231                },
    237232
    238                 /**
    239                  * Gets the document containing this element.
    240                  * @returns {CKEDITOR.dom.document} The document.
    241                  * @example
    242                  * var element = CKEDITOR.document.getById( 'example' );
    243                  * alert( <b>element.getDocument().equals( CKEDITOR.document )</b> );  // "true"
    244                  */
    245                 getDocument : function()
     233                getIndex : function( normalized )
    246234                {
    247                         return new CKEDITOR.dom.document( this.$.ownerDocument || this.$.parentNode.ownerDocument );
    248                 },
     235                        // Attention: getAddress depends on this.$
    249236
    250                 getIndex : function()
    251                 {
    252                         var $ = this.$;
     237                        var current = this.$,
     238                                index = 0;
    253239
    254                         var currentNode = $.parentNode && $.parentNode.firstChild;
    255                         var currentIndex = -1;
    256 
    257                         while ( currentNode )
     240                        while ( ( current = current.previousSibling ) )
    258241                        {
    259                                 currentIndex++;
     242                                // When normalizing, do not count it if this is an
     243                                // empty text node or if it's a text node following another one.
     244                                if ( normalized && current.nodeType == 3 &&
     245                                         ( !current.nodeValue.length ||
     246                                           ( current.previousSibling && current.previousSibling.nodeType == 3 ) ) )
     247                                {
     248                                        continue;
     249                                }
    260250
    261                                 if ( currentNode == $ )
    262                                         return currentIndex;
    263 
    264                                 currentNode = currentNode.nextSibling;
     251                                index++;
    265252                        }
    266253
    267                         return -1;
     254                        return index;
    268255                },
    269256
    270257                getNextSourceNode : function( startFromSibling, nodeType, guard )
  • _source/core/dom/range.js

     
    589589                                                startContainer = child;
    590590                                                startOffset = 0;
    591591                                        }
     592
     593                                        // Get the normalized offset.
     594                                        if ( child && child.type == CKEDITOR.NODE_ELEMENT )
     595                                                startOffset = child.getIndex( 1 );
    592596                                }
    593597
    594598                                // Normalize the start.
     
    617621                                                        endContainer = child;
    618622                                                        endOffset = 0;
    619623                                                }
     624
     625                                                // Get the normalized offset.
     626                                                if ( child && child.type == CKEDITOR.NODE_ELEMENT )
     627                                                        endOffset = child.getIndex( 1 );
    620628                                        }
    621629
    622630                                        // Normalize the end.
  • _source/core/dom/text.js

     
    6767                        return this.$.nodeValue;
    6868                },
    6969
     70                setText : function( text )
     71                {
     72                        this.$.nodeValue = text;
     73                },
     74
    7075                /**
    7176                 * Breaks this text node into two nodes at the specified offset,
    7277                 * keeping both in the tree as siblings. This node then only contains
  • _source/plugins/editingblock/plugin.js

     
    153153         */
    154154        CKEDITOR.editor.prototype.setMode = function( mode )
    155155        {
     156                this.fire( 'beforeSetMode', { newMode : mode } );
     157
    156158                var data,
    157159                        holderElement = this.getThemeSpace( 'contents' ),
    158160                        isDirty = this.checkDirty();
  • _source/plugins/selection/plugin.js

     
    9999                canUndo : false
    100100        };
    101101
     102        var fillingChar,
     103                fillingCharReady;
     104
     105        // Checks if a filling char has been used, eventualy removing it (#1272).
     106        function checkFillingChar()
     107        {
     108                if ( fillingChar )
     109                {
     110                        fillingCharReady && removeFillingChar();
     111
     112                        // Use this flag to avoid removing the filling char right after
     113                        // creating it.
     114                        fillingCharReady = !fillingCharReady;
     115                }
     116        }
     117
     118        function removeFillingChar()
     119        {
     120                if ( fillingChar )
     121                {
     122                        // We can't simply remove the filling node because the user
     123                        // will actually enlarge it when typing, so we just remove the
     124                        // invisible char from it.
     125                        fillingChar.setText( fillingChar.getText().replace( /\u200B/g, '' ) );
     126                        fillingChar = 0;
     127                }
     128        }
     129
    102130        CKEDITOR.plugins.add( 'selection',
    103131        {
    104132                init : function( editor )
    105133                {
     134                        // On WebKit only, we need a special "filling" char on some situations
     135                        // (#1272). Here we set the events that should invalidate that char.
     136                        if ( CKEDITOR.env.webkit )
     137                        {
     138                                editor.on( 'selectionChange', checkFillingChar );
     139                                editor.on( 'beforeSetMode', checkFillingChar );
     140                                editor.on( 'key', function( e )
     141                                        {
     142                                                // Remove the filling char before the left-key is
     143                                                // executed, so it'll not get blocked by it.
     144                                                switch ( e.data.keyCode )
     145                                                {
     146                                                        case 37 :       // LEFT-ARROW
     147                                                        case 8 :        // BACKSPACE
     148                                                                checkFillingChar();
     149                                                }
     150                                        });
     151
     152                                var fillingCharBeforeUndo;
     153                                editor.on( 'beforeUndoImage', function()
     154                                        {
     155                                                fillingCharBeforeUndo = fillingChar && fillingChar.getText();
     156                                                fillingCharBeforeUndo && fillingChar.setText( fillingCharBeforeUndo.replace( /\u200B/g, '' ) );
     157                                        });
     158                                editor.on( 'afterUndoImage', function()
     159                                        {
     160                                                fillingChar && fillingChar.setText( fillingCharBeforeUndo );
     161                                        });
     162                        }
     163
    106164                        editor.on( 'contentDom', function()
    107165                                {
    108166                                        var doc = editor.document,
     
    11381196                                var sel = this.getNative();
    11391197
    11401198                                if ( ranges.length )
     1199                                {
    11411200                                        sel.removeAllRanges();
     1201                                        // Remove any existing filling char first.
     1202                                        CKEDITOR.env.webkit && removeFillingChar();
     1203                                        fillingCharReady = 0;
     1204                                }
    11421205
    11431206                                for ( var i = 0 ; i < ranges.length ; i++ )
    11441207                                {
     
    11881251                                                startContainer.appendText( '' );
    11891252                                        }
    11901253
    1191                                         nativeRange.setStart( startContainer.$, range.startOffset );
     1254                                        if ( range.collapsed && CKEDITOR.env.webkit )
     1255                                        {
     1256                                                // Append a zero-width space so WebKit will not try to
     1257                                                // move the selection by itself (#1272).
     1258                                                fillingChar = this.document.createText( '\u200B' );
     1259                                                range.insertNode( fillingChar ) ;
     1260
     1261                                                var next = fillingChar.getNext();
     1262
     1263                                                // If the filling char is followed by a <br>, it'll not
     1264                                                // blink. Let's remove it in this case.
     1265                                                if ( next && next.type == CKEDITOR.NODE_ELEMENT && next.getName() == 'br' )
     1266                                                {
     1267                                                        removeFillingChar();
     1268                                                        range.moveToPosition( next, CKEDITOR.POSITION_BEFORE_START );
     1269                                                }
     1270                                                else
     1271                                                        range.moveToPosition( fillingChar, CKEDITOR.POSITION_AFTER_END );
     1272                                        }
     1273
     1274                                        nativeRange.setStart( range.startContainer.$, range.startOffset );
    11921275                                        nativeRange.setEnd( range.endContainer.$, range.endOffset );
    11931276
    11941277                                        // Select the range.
     
    13761459                :
    13771460                        function()
    13781461                        {
    1379                                 var startContainer = this.startContainer;
    1380 
    1381                                 // If we have a collapsed range, inside an empty element, we must add
    1382                                 // something to it, otherwise the caret will not be visible.
    1383                                 if ( this.collapsed && startContainer.type == CKEDITOR.NODE_ELEMENT && !startContainer.getChildCount() )
    1384                                         startContainer.append( new CKEDITOR.dom.text( '' ) );
    1385 
    1386                                 var nativeRange = this.document.$.createRange();
    1387                                 nativeRange.setStart( startContainer.$, this.startOffset );
    1388 
    1389                                 try
    1390                                 {
    1391                                         nativeRange.setEnd( this.endContainer.$, this.endOffset );
    1392                                 }
    1393                                 catch ( e )
    1394                                 {
    1395                                         // There is a bug in Firefox implementation (it would be too easy
    1396                                         // otherwise). The new start can't be after the end (W3C says it can).
    1397                                         // So, let's create a new range and collapse it to the desired point.
    1398                                         if ( e.toString().indexOf( 'NS_ERROR_ILLEGAL_VALUE' ) >= 0 )
    1399                                         {
    1400                                                 this.collapse( true );
    1401                                                 nativeRange.setEnd( this.endContainer.$, this.endOffset );
    1402                                         }
    1403                                         else
    1404                                                 throw( e );
    1405                                 }
    1406 
    1407                                 var selection = this.document.getSelection().getNative();
    1408                                 // getSelection() returns null in case when iframe is "display:none" in FF. (#6577)
    1409                                 if ( selection )
    1410                                 {
    1411                                         selection.removeAllRanges();
    1412                                         selection.addRange( nativeRange );
    1413                                 }
     1462                                this.document.getSelection().selectRanges( [ this ] );
    14141463                        };
    14151464} )();
  • _source/plugins/undo/plugin.js

     
    148148        var Image = CKEDITOR.plugins.undo.Image = function( editor )
    149149        {
    150150                this.editor = editor;
     151
     152                editor.fire( 'beforeUndoImage' );
     153
    151154                var contents = editor.getSnapshot(),
    152155                        selection       = contents && editor.getSelection();
    153156
     
    156159
    157160                this.contents   = contents;
    158161                this.bookmarks  = selection && selection.createBookmarks2( true );
     162
     163                editor.fire( 'afterUndoImage' );
    159164        };
    160165
    161166        // Attributes that browser may changing them when setting via innerHTML.
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy