| 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 | |
| 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 | |
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 ); |
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 ] ); |