Ticket #5479: 5479_19.patch
File 5479_19.patch, 12.4 KB (added by , 13 years ago) |
---|
-
_source/plugins/selection/plugin.js
99 99 canUndo : false 100 100 }; 101 101 102 function createFillingChar( doc)102 function createFillingChar( range ) 103 103 { 104 var doc = range.document; 104 105 removeFillingChar( doc ); 105 106 107 // Place a zero-width space so browser will be able to 108 // blink the cursor normally (#1272). 106 109 var fillingChar = doc.createText( '\u200B' ); 107 110 doc.setCustomData( 'cke-fillingChar', fillingChar ); 108 111 109 return fillingChar; 110 } 112 range.insertNode( fillingChar ); 113 114 var next = fillingChar.getNext(); 115 116 // If the filling char is followed by a <br>, without 117 // having something before it, it'll not blink. 118 // Let's remove it in this case. 119 if ( next && !fillingChar.getPrevious() && next.type == CKEDITOR.NODE_ELEMENT && next.getName() == 'br' ) 120 { 121 removeFillingChar( this.document ); 122 range.moveToPosition( next, CKEDITOR.POSITION_BEFORE_START ); 123 } 124 else 125 range.moveToPosition( fillingChar, CKEDITOR.POSITION_AFTER_END ); 126 } 111 127 112 128 function getFillingChar( doc ) 113 129 { 114 return doc && doc.getCustomData( 'cke-fillingChar' ); 115 } 130 var filling = doc && doc.getCustomData( 'cke-fillingChar' ); 131 if ( filling ) 132 { 133 // Test if the filling node is still inside document, 134 // unwise clean up everything. 135 try 136 { 137 if ( !filling.getAscendant( 'html' ) ) 138 throw ''; 139 } 140 catch( er ) 141 { 142 doc.removeCustomData( 'cke-fillingChar' ); 143 doc.removeCustomData( 'cke-fillingChar-ready'); 144 filling = null; 145 } 146 } 147 return filling; 148 } 116 149 117 150 // Checks if a filling char has been used, eventualy removing it (#1272). 118 151 function checkFillingChar( doc ) … … 122 155 { 123 156 // Use this flag to avoid removing the filling char right after 124 157 // creating it. 125 if ( fillingChar.getCustomData( 'ready' ) )158 if ( doc.getCustomData( 'cke-fillingChar-ready' ) ) 126 159 removeFillingChar( doc ); 127 160 else 128 fillingChar.setCustomData( 'ready', 1 );161 doc.setCustomData( 'cke-fillingChar-ready', 1 ); 129 162 } 130 163 } 131 164 132 165 function removeFillingChar( doc ) 133 166 { 134 var fillingChar = doc && doc.removeCustomData( 'cke-fillingChar');167 var fillingChar = getFillingChar( doc ); 135 168 if ( fillingChar ) 136 169 { 137 170 // We can't simply remove the filling node because the user … … 139 172 // invisible char from it. 140 173 fillingChar.setText( fillingChar.getText().replace( /\u200B/g, '' ) ); 141 174 fillingChar = 0; 175 doc.removeCustomData( 'cke-fillingChar' ); 176 doc.removeCustomData( 'cke-fillingChar-ready'); 142 177 } 143 178 } 144 179 … … 148 183 { 149 184 // On WebKit only, we need a special "filling" char on some situations 150 185 // (#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 }); 186 editor.on( 'selectionChange', function() { checkFillingChar( editor.document ); } ); 187 editor.on( 'beforeSetMode', function() { removeFillingChar( editor.document ); } ); 188 editor.on( 'key', function( e ) 189 { 190 // Remove the filling char before some keys get 191 // executed, so they'll not get blocked by it. 192 switch ( e.data.keyCode ) 193 { 194 case 37 : // LEFT-ARROW 195 case 39 : // RIGHT-ARROW 196 case 8 : // BACKSPACE 197 removeFillingChar( editor.document ); 198 } 199 } ); 167 200 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, '' ) ); 201 var fillingCharBefore; 202 function beforeData() 203 { 204 205 var fillingChar = getFillingChar( editor.document ); 206 if ( fillingChar ) 207 { 208 fillingCharBefore = fillingChar.getText(); 209 fillingChar.setText( fillingCharBefore.replace( /\u200B/g, '' ) ); 174 210 } 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 }211 } 212 function afterData() 213 { 214 var fillingChar = getFillingChar( editor.document ); 215 fillingChar && fillingChar.setText( fillingCharBefore ); 216 } 217 editor.on( 'beforeUndoImage', beforeData ); 218 editor.on( 'afterUndoImage', afterData ); 219 editor.on( 'beforeGetData', beforeData, null, null, 0 ); 220 editor.on( 'getData', afterData ); 185 221 186 222 editor.on( 'contentDom', function() 187 223 { … … 1194 1230 * by clearing up the original selection. 1195 1231 * @param {CKEDITOR.dom.range} ranges 1196 1232 */ 1197 selectRanges : function( ranges )1233 selectRanges : function( ranges, forceExpand ) 1198 1234 { 1199 1235 if ( this.isLocked ) 1200 1236 { … … 1217 1253 } 1218 1254 1219 1255 if ( ranges[ 0 ] ) 1220 ranges[ 0 ].select( );1256 ranges[ 0 ].select( forceExpand ); 1221 1257 1222 1258 this.reset(); 1223 1259 } … … 1233 1269 { 1234 1270 sel.removeAllRanges(); 1235 1271 // Remove any existing filling char first. 1236 CKEDITOR.env.webkit &&removeFillingChar( this.document );1272 removeFillingChar( this.document ); 1237 1273 } 1238 1274 1239 1275 for ( var i = 0 ; i < ranges.length ; i++ ) … … 1284 1320 startContainer.appendText( '' ); 1285 1321 } 1286 1322 1287 if ( range.collapsed && CKEDITOR.env.webkit ) 1288 { 1289 // Append a zero-width space so WebKit will not try to 1290 // move the selection by itself (#1272). 1291 var fillingChar = createFillingChar( this.document ); 1292 range.insertNode( fillingChar ) ; 1323 if ( range.collapsed && ( forceExpand || CKEDITOR.env.webkit ) ) 1324 createFillingChar( range ); 1293 1325 1294 var next = fillingChar.getNext();1295 1296 // If the filling char is followed by a <br>, whithout1297 // having something before it, it'll not blink.1298 // Let's remove it in this case.1299 if ( next && !fillingChar.getPrevious() && next.type == CKEDITOR.NODE_ELEMENT && next.getName() == 'br' )1300 {1301 removeFillingChar( this.document );1302 range.moveToPosition( next, CKEDITOR.POSITION_BEFORE_START );1303 }1304 else1305 range.moveToPosition( fillingChar, CKEDITOR.POSITION_AFTER_END );1306 }1307 1308 1326 nativeRange.setStart( range.startContainer.$, range.startOffset ); 1309 1327 1310 1328 try … … 1394 1412 start.scrollIntoView(); 1395 1413 } 1396 1414 }; 1397 })();1398 1415 1399 ( function()1400 {1401 1416 var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true ), 1402 1417 fillerTextRegex = /\ufeff|\u00a0/, 1403 1418 nonCells = { table:1,tbody:1,tr:1 }; … … 1411 1426 var isStartMarkerAlone; 1412 1427 var dummySpan; 1413 1428 1429 collapsed && forceExpand && createFillingChar( this ); 1430 1414 1431 // IE doesn't support selecting the entire table row/cell, move the selection into cells, e.g. 1415 1432 // <table><tbody><tr>[<td>cell</b></td>... => <table><tbody><tr><td>[cell</td>... 1416 1433 if ( this.startContainer.type == CKEDITOR.NODE_ELEMENT && this.startContainer.getName() in nonCells … … 1508 1525 this.document.fire( 'selectionchange' ); 1509 1526 } 1510 1527 : 1511 function( )1528 function( forceExpand ) 1512 1529 { 1513 this.document.getSelection().selectRanges( [ this ] );1530 this.document.getSelection().selectRanges( [ this ], forceExpand ); 1514 1531 }; 1515 } )(); 1532 1533 })(); -
_source/plugins/wysiwygarea/plugin.js
11 11 (function() 12 12 { 13 13 // List of elements in which has no way to move editing focus outside. 14 var nonExitableElementNames = { table:1,pre:1 };14 var nonExitableElementNames = { table:1,pre:1, ul:1,ol:1,dl:1,blockquote:1,form:1 }; 15 15 16 16 // Matching an empty paragraph at the end of document. 17 17 var emptyParagraphRegexp = /(^|<body\b[^>]*>)\s*<(p|div|address|h\d|center)[^>]*>\s*(?:<br[^>]*>| |\u00A0| )?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi; … … 430 430 editor.selectionChange(); 431 431 } 432 432 } 433 434 // All browsers are incapable to moving cursor out of certain non-exitable 435 // blocks (e.g. table, list, pre) at the end of document, make this happen by 436 // place a bogus node there, which would be later removed by dataprocessor. 437 var walkerRange = new CKEDITOR.dom.range( editor.document ), 438 walker = new CKEDITOR.dom.walker( walkerRange ); 439 walkerRange.selectNodeContents( body ); 440 walker.evaluator = function( node ) 441 { 442 return node.type == CKEDITOR.NODE_ELEMENT && ( node.getName() in nonExitableElementNames ); 443 }; 444 walker.guard = function( node, isMoveout ) 445 { 446 return !( ( node.type == CKEDITOR.NODE_TEXT && isNotWhitespace( node ) ) || isMoveout ); 447 }; 448 449 if ( walker.previous() ) 450 { 451 editor.fire( 'updateSnapshot' ); 452 restoreDirty( editor ); 453 CKEDITOR.env.ie && restoreSelection( selection ); 454 455 var paddingBlock; 456 if ( enterMode != CKEDITOR.ENTER_BR ) 457 paddingBlock = body.append( new CKEDITOR.dom.element( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ); 458 else 459 paddingBlock = body; 460 461 if ( !CKEDITOR.env.ie ) 462 paddingBlock.appendBogus(); 463 } 464 } 433 } 465 434 466 435 CKEDITOR.plugins.add( 'wysiwygarea', 467 436 { … … 1216 1185 } 1217 1186 }); 1218 1187 1219 } 1220 }); 1188 // All browsers are incapable to moving cursor out of certain non-exitable 1189 // blocks (e.g. table, list, pre) at the end of document, enable this when 1190 // user clicks on the padding bottom area of body. 1191 editor.addCss( 'body{padding-bottom: 20px;}'); 1192 editor.on( 'contentDom', function () 1193 { 1194 var doc = editor.document, 1195 body = doc.getBody(); 1196 1197 body.on( 'click', function ( evt ) 1198 { 1199 evt = evt.data; 1200 1201 // All browsers are incapable to moving cursor out of certain non-exitable 1202 // blocks (e.g. table, list, pre) at the end of document, make this happen by 1203 // place a bogus node there, which would be later removed by dataprocessor. 1204 if ( ( evt.$.offsetY || evt.$.layerY || evt.$.y ) > body.$.clientHeight - parseInt( body.getComputedStyle( 'padding-bottom' ) ) ) 1205 { 1206 var walkerRange = new CKEDITOR.dom.range( editor.document ), 1207 walker = new CKEDITOR.dom.walker( walkerRange ); 1208 walkerRange.selectNodeContents( body ); 1209 walker.evaluator = function( node ) 1210 { 1211 return node.type == CKEDITOR.NODE_ELEMENT && ( node.getName() in nonExitableElementNames ); 1212 }; 1213 walker.guard = function( node, isMoveout ) 1214 { 1215 return !( ( node.type == CKEDITOR.NODE_TEXT && isNotWhitespace( node ) ) || isMoveout ); 1216 }; 1217 1218 if ( walker.previous() ) 1219 { 1220 var range = new CKEDITOR.dom.range( doc ); 1221 range.moveToPosition( body, CKEDITOR.POSITION_BEFORE_END ); 1222 range.select( 1 ); 1223 evt.preventDefault(); 1224 } 1225 } 1226 }); 1227 }); 1228 } 1229 }); 1221 1230 1222 1231 // Fixing Firefox 'Back-Forward Cache' break design mode. (#4514) 1223 1232 if ( CKEDITOR.env.gecko ) -
_source/plugins/domiterator/plugin.js
108 108 { 109 109 this._.lastNode = this._.docEndMarker = range.document.createText( '' ); 110 110 this._.lastNode.insertAfter( lastNode ); 111 // If the current last is a bookmark, to make sure it will be included in the range, 112 // we need another marker as "getNextSourceNode" will always skip it. 113 if ( !bookmarkGuard( lastNode) ) 114 this._.lastNode.clone().insertAfter( lastNode ); 111 115 } 112 116 113 117 // Let's reuse this variable.