Ticket #1272: 1272_6.patch
File 1272_6.patch, 10.4 KB (added by , 14 years ago) |
---|
-
_source/core/dom/node.js
182 182 }, 183 183 184 184 /** 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 /** 185 197 * Retrieves a uniquely identifiable tree address for this node. 186 198 * The tree address returns is an array of integers, with each integer 187 199 * indicating a child index of a DOM node, starting from … … 204 216 while ( node && node != $documentElement ) 205 217 { 206 218 var parentNode = node.parentNode; 207 var currentIndex = -1;208 219 209 220 if ( parentNode ) 210 221 { 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 ) ); 230 225 } 231 226 232 227 node = parentNode; … … 235 230 return address; 236 231 }, 237 232 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 ) 246 234 { 247 return new CKEDITOR.dom.document( this.$.ownerDocument || this.$.parentNode.ownerDocument ); 248 }, 235 // Attention: getAddress depends on this.$ 249 236 250 getIndex : function() 251 { 252 var $ = this.$; 237 var current = this.$, 238 index = 0; 253 239 254 var currentNode = $.parentNode && $.parentNode.firstChild; 255 var currentIndex = -1; 256 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 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 102 130 CKEDITOR.plugins.add( 'selection', 103 131 { 104 132 init : function( editor ) 105 133 { 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 106 164 editor.on( 'contentDom', function() 107 165 { 108 166 var doc = editor.document, … … 1138 1196 var sel = this.getNative(); 1139 1197 1140 1198 if ( ranges.length ) 1199 { 1141 1200 sel.removeAllRanges(); 1201 // Remove any existing filling char first. 1202 CKEDITOR.env.webkit && removeFillingChar(); 1203 fillingCharReady = 0; 1204 } 1142 1205 1143 1206 for ( var i = 0 ; i < ranges.length ; i++ ) 1144 1207 { … … 1188 1251 startContainer.appendText( '' ); 1189 1252 } 1190 1253 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 ); 1192 1275 nativeRange.setEnd( range.endContainer.$, range.endOffset ); 1193 1276 1194 1277 // Select the range. … … 1376 1459 : 1377 1460 function() 1378 1461 { 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 ] ); 1414 1463 }; 1415 1464 } )(); -
_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.