Ticket #1272: 1272_7.patch
File 1272_7.patch, 10.3 KB (added by , 13 years ago) |
---|
-
_source/core/dom/node.js
204 204 while ( node && node != $documentElement ) 205 205 { 206 206 var parentNode = node.parentNode; 207 var currentIndex = -1;208 207 209 208 if ( parentNode ) 210 209 { 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 ) ); 230 213 } 231 214 232 215 node = parentNode; … … 247 230 return new CKEDITOR.dom.document( this.$.ownerDocument || this.$.parentNode.ownerDocument ); 248 231 }, 249 232 250 getIndex : function( )233 getIndex : function( normalized ) 251 234 { 252 var $ = this.$;235 // Attention: getAddress depends on this.$ 253 236 254 var current Node = $.parentNode && $.parentNode.firstChild;255 var currentIndex = -1;237 var current = this.$, 238 index = 0; 256 239 257 while ( currentNode)240 while ( ( current = current.previousSibling ) ) 258 241 { 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 } 260 250 261 if ( currentNode == $ ) 262 return currentIndex; 263 264 currentNode = currentNode.nextSibling; 251 index++; 265 252 } 266 253 267 return -1;254 return index; 268 255 }, 269 256 270 257 getNextSourceNode : function( startFromSibling, nodeType, guard ) -
_source/core/dom/range.js
589 589 startContainer = child; 590 590 startOffset = 0; 591 591 } 592 593 // Get the normalized offset. 594 if ( child && child.type == CKEDITOR.NODE_ELEMENT ) 595 startOffset = child.getIndex( 1 ); 592 596 } 593 597 594 598 // Normalize the start. … … 617 621 endContainer = child; 618 622 endOffset = 0; 619 623 } 624 625 // Get the normalized offset. 626 if ( child && child.type == CKEDITOR.NODE_ELEMENT ) 627 endOffset = child.getIndex( 1 ); 620 628 } 621 629 622 630 // Normalize the end. -
_source/core/dom/text.js
67 67 return this.$.nodeValue; 68 68 }, 69 69 70 setText : function( text ) 71 { 72 this.$.nodeValue = text; 73 }, 74 70 75 /** 71 76 * Breaks this text node into two nodes at the specified offset, 72 77 * keeping both in the tree as siblings. This node then only contains -
_source/plugins/editingblock/plugin.js
153 153 */ 154 154 CKEDITOR.editor.prototype.setMode = function( mode ) 155 155 { 156 this.fire( 'beforeSetMode', { newMode : mode } ); 157 156 158 var data, 157 159 holderElement = this.getThemeSpace( 'contents' ), 158 160 isDirty = this.checkDirty(); -
_source/plugins/selection/plugin.js
99 99 canUndo : false 100 100 }; 101 101 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 102 145 CKEDITOR.plugins.add( 'selection', 103 146 { 104 147 init : function( editor ) 105 148 { 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 106 186 editor.on( 'contentDom', function() 107 187 { 108 188 var doc = editor.document, … … 1138 1218 var sel = this.getNative(); 1139 1219 1140 1220 if ( ranges.length ) 1221 { 1141 1222 sel.removeAllRanges(); 1223 // Remove any existing filling char first. 1224 CKEDITOR.env.webkit && removeFillingChar( this.document ); 1225 } 1142 1226 1143 1227 for ( var i = 0 ; i < ranges.length ; i++ ) 1144 1228 { … … 1188 1272 startContainer.appendText( '' ); 1189 1273 } 1190 1274 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 ); 1192 1297 nativeRange.setEnd( range.endContainer.$, range.endOffset ); 1193 1298 1194 1299 // Select the range. … … 1376 1481 : 1377 1482 function() 1378 1483 { 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 ] ); 1414 1485 }; 1415 1486 } )(); -
_source/plugins/undo/plugin.js
148 148 var Image = CKEDITOR.plugins.undo.Image = function( editor ) 149 149 { 150 150 this.editor = editor; 151 152 editor.fire( 'beforeUndoImage' ); 153 151 154 var contents = editor.getSnapshot(), 152 155 selection = contents && editor.getSelection(); 153 156 … … 156 159 157 160 this.contents = contents; 158 161 this.bookmarks = selection && selection.createBookmarks2( true ); 162 163 editor.fire( 'afterUndoImage' ); 159 164 }; 160 165 161 166 // Attributes that browser may changing them when setting via innerHTML.