Ticket #1272: 1272_7.patch

File 1272_7.patch, 10.3 KB (added by Frederico Caldeira Knabben, 13 years ago)
  • _source/core/dom/node.js

     
    204204                        while ( node && node != $documentElement )
    205205                        {
    206206                                var parentNode = node.parentNode;
    207                                 var currentIndex = -1;
    208207
    209208                                if ( parentNode )
    210209                                {
    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 );
     210                                        // Get the node index. For performance, call getIndex
     211                                        // directly, instead of creating a new node object.
     212                                        address.unshift( this.getIndex.call( { $ : node }, normalized ) );
    230213                                }
    231214
    232215                                node = parentNode;
     
    247230                        return new CKEDITOR.dom.document( this.$.ownerDocument || this.$.parentNode.ownerDocument );
    248231                },
    249232
    250                 getIndex : function()
     233                getIndex : function( normalized )
    251234                {
    252                         var $ = this.$;
     235                        // Attention: getAddress depends on this.$
    253236
    254                         var currentNode = $.parentNode && $.parentNode.firstChild;
    255                         var currentIndex = -1;
     237                        var current = this.$,
     238                                index = 0;
    256239
    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        function createFillingChar( doc )
     103        {
     104                removeFillingChar( doc );
     105
     106                var fillingChar = doc.createText( '\u200B' );
     107                doc.setCustomData( 'cke-fillingChar', fillingChar );
     108
     109                return fillingChar;
     110        }
     111
     112        function getFillingChar( doc )
     113        {
     114                return doc && doc.getCustomData( 'cke-fillingChar' );
     115        }
     116
     117        // Checks if a filling char has been used, eventualy removing it (#1272).
     118        function checkFillingChar( doc )
     119        {
     120                var fillingChar = doc && getFillingChar( doc );
     121                if ( fillingChar )
     122                {
     123                        // Use this flag to avoid removing the filling char right after
     124                        // creating it.
     125                        if ( fillingChar.getCustomData( 'ready' ) )
     126                                removeFillingChar( doc );
     127                        else
     128                                fillingChar.setCustomData( 'ready', 1 );
     129                }
     130        }
     131
     132        function removeFillingChar( doc )
     133        {
     134                var fillingChar = doc && doc.removeCustomData( 'cke-fillingChar' );
     135                if ( fillingChar )
     136                {
     137                        // We can't simply remove the filling node because the user
     138                        // will actually enlarge it when typing, so we just remove the
     139                        // invisible char from it.
     140                        fillingChar.setText( fillingChar.getText().replace( /\u200B/g, '' ) );
     141                        fillingChar = 0;
     142                }
     143        }
     144
    102145        CKEDITOR.plugins.add( 'selection',
    103146        {
    104147                init : function( editor )
    105148                {
     149                        // On WebKit only, we need a special "filling" char on some situations
     150                        // (#1272). Here we set the events that should invalidate that char.
     151                        if ( CKEDITOR.env.webkit )
     152                        {
     153                                editor.on( 'selectionChange', function() { checkFillingChar( editor.document ); } );
     154                                editor.on( 'beforeSetMode', function() { removeFillingChar( editor.document ); } );
     155                                editor.on( 'key', function( e )
     156                                        {
     157                                                // Remove the filling char before some keys get
     158                                                // executed, so they'll not get blocked by it.
     159                                                switch ( e.data.keyCode )
     160                                                {
     161                                                        case 37 :       // LEFT-ARROW
     162                                                        case 39 :       // RIGHT-ARROW
     163                                                        case 8 :        // BACKSPACE
     164                                                                removeFillingChar( editor.document );
     165                                                }
     166                                        });
     167
     168                                var fillingCharBefore;
     169                                function beforeData()
     170                                {
     171                                        var fillingChar = getFillingChar( editor.document );
     172                                        fillingCharBefore = fillingChar && fillingChar.getText();
     173                                        fillingCharBefore && fillingChar.setText( fillingCharBefore.replace( /\u200B/g, '' ) );
     174                                }
     175                                function afterData()
     176                                {
     177                                                var fillingChar = getFillingChar( editor.document );
     178                                                fillingChar && fillingChar.setText( fillingCharBefore );
     179                                }
     180                                editor.on( 'beforeUndoImage', beforeData );
     181                                editor.on( 'afterUndoImage', afterData );
     182                                editor.on( 'beforeGetData', beforeData, null, null, 0 );
     183                                editor.on( 'getData', afterData );
     184                        }
     185
    106186                        editor.on( 'contentDom', function()
    107187                                {
    108188                                        var doc = editor.document,
     
    11381218                                var sel = this.getNative();
    11391219
    11401220                                if ( ranges.length )
     1221                                {
    11411222                                        sel.removeAllRanges();
     1223                                        // Remove any existing filling char first.
     1224                                        CKEDITOR.env.webkit && removeFillingChar( this.document );
     1225                                }
    11421226
    11431227                                for ( var i = 0 ; i < ranges.length ; i++ )
    11441228                                {
     
    11881272                                                startContainer.appendText( '' );
    11891273                                        }
    11901274
    1191                                         nativeRange.setStart( startContainer.$, range.startOffset );
     1275                                        if ( range.collapsed && CKEDITOR.env.webkit )
     1276                                        {
     1277                                                // Append a zero-width space so WebKit will not try to
     1278                                                // move the selection by itself (#1272).
     1279                                                fillingChar = createFillingChar( this.document );
     1280                                                range.insertNode( fillingChar ) ;
     1281
     1282                                                var next = fillingChar.getNext();
     1283
     1284                                                // If the filling char is followed by a <br>, whithout
     1285                                                // having something before it, it'll not blink.
     1286                                                // Let's remove it in this case.
     1287                                                if ( next && !fillingChar.getPrevious() && next.type == CKEDITOR.NODE_ELEMENT && next.getName() == 'br' )
     1288                                                {
     1289                                                        removeFillingChar( this.document );
     1290                                                        range.moveToPosition( next, CKEDITOR.POSITION_BEFORE_START );
     1291                                                }
     1292                                                else
     1293                                                        range.moveToPosition( fillingChar, CKEDITOR.POSITION_AFTER_END );
     1294                                        }
     1295
     1296                                        nativeRange.setStart( range.startContainer.$, range.startOffset );
    11921297                                        nativeRange.setEnd( range.endContainer.$, range.endOffset );
    11931298
    11941299                                        // Select the range.
     
    13761481                :
    13771482                        function()
    13781483                        {
    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                                 }
     1484                                this.document.getSelection().selectRanges( [ this ] );
    14141485                        };
    14151486} )();
  • _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 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy