// [Edge] Starting from EdgeHTML 14.14393, it does not support `setActive`. We need to use focus which
// causes unexpected scroll. Store scrollTop value so it can be restored after focusing editor.
- // Scroll only happens if the editor is focused for the first time. (#14825)
+ // Scroll only happens if the editor is focused for the first time. (http://dev.ckeditor.com/ticket/14825)
if ( CKEDITOR.env.edge && CKEDITOR.env.version > 14 && !this.hasFocus && this.getDocument().equals( CKEDITOR.document ) ) {
this.editor._.previousScrollTop = this.$.scrollTop;
}
if ( CKEDITOR.env.ie && !( CKEDITOR.env.edge && CKEDITOR.env.version > 14 ) && this.getDocument().equals( CKEDITOR.document ) ) {
this.$.setActive();
} else {
- this.$.focus();
+ // We have no control over exactly what happens when the native `focus` method is called,
+ // so save the scroll position and restore it later.
+ if ( CKEDITOR.env.chrome ) {
+ var scrollPos = this.$.scrollTop;
+ this.$.focus();
+ this.$.scrollTop = scrollPos;
+ } else {
+ this.$.focus();
+ }
}
} catch ( e ) {
// IE throws unspecified error when focusing editable after closing dialog opened on nested editable.
throw e;
}
- // Remedy if Safari doens't applies focus properly. (#279)
+ // Remedy if Safari doens't applies focus properly. (http://dev.ckeditor.com/ticket/279)
if ( CKEDITOR.env.safari && !this.isInline() ) {
active = CKEDITOR.document.getActive();
if ( !active.equals( this.getWindow().getFrame() ) )
// The "focusin/focusout" events bubbled, e.g. If there are elements with layout
// they fire this event when clicking in to edit them but it must be ignored
- // to allow edit their contents. (#4682)
+ // to allow edit their contents. (http://dev.ckeditor.com/ticket/4682)
fn = isNotBubbling( fn, this );
args[ 0 ] = name;
args[ 1 ] = fn;
* @param {String} text
*/
insertText: function( text ) {
- // Focus the editor before calling transformPlainTextToHtml. (#12726)
+ // Focus the editor before calling transformPlainTextToHtml. (http://dev.ckeditor.com/ticket/12726)
this.editor.focus();
this.insertHtml( this.transformPlainTextToHtml( text ), 'text' );
},
insertElement: function( element, range ) {
var editor = this.editor;
- // Prepare for the insertion. For example - focus editor (#11848).
+ // Prepare for the insertion. For example - focus editor (http://dev.ckeditor.com/ticket/11848).
editor.focus();
editor.fire( 'saveSnapshot' );
range = selection.getRanges()[ 0 ];
}
- // Insert element into first range only and ignore the rest (#11183).
+ // Insert element into first range only and ignore the rest (http://dev.ckeditor.com/ticket/11183).
if ( this.insertElementIntoRange( element, range ) ) {
range.moveToPosition( element, CKEDITOR.POSITION_AFTER_END );
// If we're inserting a block element, the new cursor position must be
- // optimized. (#3100,#5436,#8950)
+ // optimized. (http://dev.ckeditor.com/ticket/3100,http://dev.ckeditor.com/ticket/5436,http://dev.ckeditor.com/ticket/8950)
if ( isBlock ) {
// Find next, meaningful element.
var next = element.getNext( function( node ) {
range.splitElement( current );
// If we're in an empty block which indicate a new paragraph,
- // simply replace it with the inserting block.(#3664)
+ // simply replace it with the inserting block.(http://dev.ckeditor.com/ticket/3664)
else if ( range.checkStartOfBlock() && range.checkEndOfBlock() ) {
range.setStartBefore( current );
range.collapse( true );
range.checkEndOfBlock() &&
path.block &&
!range.root.equals( path.block ) &&
- // Do not remove a block with bookmarks. (#13465)
+ // Do not remove a block with bookmarks. (http://dev.ckeditor.com/ticket/13465)
!hasBookmarks( path.block ) ) {
range.moveToPosition( path.block, CKEDITOR.POSITION_BEFORE_START );
path.block.remove();
// IE considers control-type element as separate
// focus host when selected, avoid destroying the
- // selection in such case. (#5812) (#8949)
+ // selection in such case. (http://dev.ckeditor.com/ticket/5812) (http://dev.ckeditor.com/ticket/8949)
if ( ieSel && ieSel.type == 'Control' )
return;
}, null, null, -1 );
if ( CKEDITOR.env.webkit ) {
- // [WebKit] Save scrollTop value so it can be used when restoring locked selection. (#14659)
+ // [WebKit] Save scrollTop value so it can be used when restoring locked selection. (http://dev.ckeditor.com/ticket/14659)
this.on( 'scroll', function() {
editor._.previousScrollTop = editor.editable().$.scrollTop;
}, null, null, -1 );
}
// [Edge] This is the other part of the workaround for Edge which restores saved
- // scrollTop value and removes listener which is not needed anymore. (#14825)
+ // scrollTop value and removes listener which is not needed anymore. (http://dev.ckeditor.com/ticket/14825)
if ( CKEDITOR.env.edge && CKEDITOR.env.version > 14 ) {
var fixScrollOnFocus = function() {
// Pass this configuration to styles system.
this.setCustomData( 'cke_includeReadonly', !editor.config.disableReadonlyStyling );
- // Prevent the browser opening read-only links. (#6032 & #10912)
+ // Prevent the browser opening read-only links. (http://dev.ckeditor.com/ticket/6032 & http://dev.ckeditor.com/ticket/10912)
this.attachListener( this, 'click', function( evt ) {
evt = evt.data;
var backspaceOrDelete = { 8: 1, 46: 1 };
// Override keystrokes which should have deletion behavior
- // on fully selected element . (#4047) (#7645)
+ // on fully selected element . (http://dev.ckeditor.com/ticket/4047) (http://dev.ckeditor.com/ticket/7645)
this.attachListener( editor, 'key', function( evt ) {
if ( editor.readOnly )
return true;
var keyCode = evt.data.domEvent.getKey(),
isHandled;
+ // Prevent of reading path of empty range (http://dev.ckeditor.com/ticket/13096, #457).
+ var sel = editor.getSelection();
+ if ( sel.getRanges().length === 0 ) {
+ return;
+ }
+
// Backspace OR Delete.
if ( keyCode in backspaceOrDelete ) {
- var sel = editor.getSelection(),
- selected,
+ var selected,
range = sel.getRanges()[ 0 ],
path = range.startPath(),
block,
next,
rtl = keyCode == 8;
+
if (
- // [IE<11] Remove selected image/anchor/etc here to avoid going back in history. (#10055)
+ // [IE<11] Remove selected image/anchor/etc here to avoid going back in history. (http://dev.ckeditor.com/ticket/10055)
( CKEDITOR.env.ie && CKEDITOR.env.version < 11 && ( selected = sel.getSelectedElement() ) ) ||
- // Remove the entire list/table on fully selected content. (#7645)
+ // Remove the entire list/table on fully selected content. (http://dev.ckeditor.com/ticket/7645)
( selected = getSelectedTableList( sel ) ) ) {
// Make undo snapshot.
editor.fire( 'saveSnapshot' );
// Delete any element that 'hasLayout' (e.g. hr,table) in IE8 will
- // break up the selection, safely manage it here. (#4795)
+ // break up the selection, safely manage it here. (http://dev.ckeditor.com/ticket/4795)
range.moveToPosition( selected, CKEDITOR.POSITION_BEFORE_START );
// Remove the control manually.
selected.remove();
isHandled = 1;
} else if ( range.collapsed ) {
- // Handle the following special cases: (#6217)
+ // Handle the following special cases: (http://dev.ckeditor.com/ticket/6217)
// 1. Del/Backspace key before/after table;
// 2. Backspace Key after start of table.
if ( ( block = path.block ) &&
editor.fire( 'doubleclick', data );
} );
- // Prevent automatic submission in IE #6336
+ // Prevent automatic submission in IE http://dev.ckeditor.com/ticket/6336
CKEDITOR.env.ie && this.attachListener( this, 'click', blockInputClick );
- // Gecko/Webkit need some help when selecting control type elements. (#3448)
- // We apply same behavior for IE Edge. (#13386)
+ // Gecko/Webkit need some help when selecting control type elements. (http://dev.ckeditor.com/ticket/3448)
+ // We apply same behavior for IE Edge. (http://dev.ckeditor.com/ticket/13386)
if ( !CKEDITOR.env.ie || CKEDITOR.env.edge ) {
this.attachListener( this, 'mousedown', function( ev ) {
var control = ev.data.getTarget();
- // #11727. Note: htmlDP assures that input/textarea/select have contenteditable=false
+ // http://dev.ckeditor.com/ticket/11727. Note: htmlDP assures that input/textarea/select have contenteditable=false
// attributes. However, they also have data-cke-editable attribute, so isReadOnly() returns false,
// and therefore those elements are correctly selected by this code.
if ( control.is( 'img', 'hr', 'input', 'textarea', 'select' ) && !control.isReadOnly() ) {
editor.getSelection().selectElement( control );
- // Prevent focus from stealing from the editable. (#9515)
+ // Prevent focus from stealing from the editable. (http://dev.ckeditor.com/ticket/9515)
if ( control.is( 'input', 'textarea', 'select' ) )
ev.data.preventDefault();
}
} );
}
- // For some reason, after click event is done, IE Edge loses focus on the selected element. (#13386)
+ // For some reason, after click event is done, IE Edge loses focus on the selected element. (http://dev.ckeditor.com/ticket/13386)
if ( CKEDITOR.env.edge ) {
this.attachListener( this, 'mouseup', function( ev ) {
var selectedElement = ev.data.getTarget();
}
// Prevent right click from selecting an empty block even
- // when selection is anchored inside it. (#5845)
+ // when selection is anchored inside it. (http://dev.ckeditor.com/ticket/5845)
if ( CKEDITOR.env.gecko ) {
this.attachListener( this, 'mouseup', function( ev ) {
if ( ev.data.$.button == 2 ) {
}
// Prevent Webkit/Blink from going rogue when joining
- // blocks on BACKSPACE/DEL (#11861,#9998).
+ // blocks on BACKSPACE/DEL (http://dev.ckeditor.com/ticket/11861,http://dev.ckeditor.com/ticket/9998).
if ( CKEDITOR.env.webkit ) {
this.attachListener( editor, 'key', function( evt ) {
if ( editor.readOnly ) {
if ( !( key in backspaceOrDelete ) )
return;
+ // Prevent of reading path of empty range (http://dev.ckeditor.com/ticket/13096, #457).
+ var sel = editor.getSelection();
+ if ( sel.getRanges().length === 0 ) {
+ return;
+ }
+
var backspace = key == 8,
- range = editor.getSelection().getRanges()[ 0 ],
+ range = sel.getRanges()[ 0 ],
startPath = range.startPath();
if ( range.collapsed ) {
return;
}
- // Scroll to the new position of the caret (#11960).
+ // Scroll to the new position of the caret (http://dev.ckeditor.com/ticket/11960).
editor.getSelection().scrollIntoView();
editor.fire( 'saveSnapshot' );
* @member CKEDITOR.editor
* @param {CKEDITOR.dom.element/CKEDITOR.editable} [elementOrEditable] The
* DOM element to become the editable or a {@link CKEDITOR.editable} object.
+ * @returns {CKEDITOR.dom.element/null} The editor's editable element, or `null` if not available.
*/
CKEDITOR.editor.prototype.editable = function( element ) {
var editable = this._.editable;
CKEDITOR.on( 'instanceLoaded', function( evt ) {
var editor = evt.editor;
- // and flag that the element was locked by our code so it'll be editable by the editor functions (#6046).
+ // and flag that the element was locked by our code so it'll be editable by the editor functions (http://dev.ckeditor.com/ticket/6046).
editor.on( 'insertElement', function( evt ) {
var element = evt.data;
if ( element.type == CKEDITOR.NODE_ELEMENT && ( element.is( 'input' ) || element.is( 'textarea' ) ) ) {
if ( editor.readOnly )
return;
- // Auto fixing on some document structure weakness to enhance usabilities. (#3190 and #3189)
+ // Auto fixing on some document structure weakness to enhance usabilities. (http://dev.ckeditor.com/ticket/3190 and http://dev.ckeditor.com/ticket/3189)
var sel = editor.getSelection();
- // Do it only when selection is not locked. (#8222)
+ // Do it only when selection is not locked. (http://dev.ckeditor.com/ticket/8222)
if ( sel && !sel.isLocked ) {
var isDirty = editor.checkDirty();
} );
} );
- // #9222: Show text cursor in Gecko.
+ // http://dev.ckeditor.com/ticket/9222: Show text cursor in Gecko.
// Show default cursor over control elements on all non-IEs.
CKEDITOR.addCss( '.cke_editable{cursor:text}.cke_editable img,.cke_editable input,.cke_editable textarea{cursor:default}' );
// Matching an empty paragraph at the end of document.
emptyParagraphRegexp = /(^|<body\b[^>]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:<br[^>]*>| |\u00A0| )?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi;
- // Auto-fixing block-less content by wrapping paragraph (#3190), prevent
- // non-exitable-block by padding extra br.(#3189)
+ // Auto-fixing block-less content by wrapping paragraph (http://dev.ckeditor.com/ticket/3190), prevent
+ // non-exitable-block by padding extra br.(http://dev.ckeditor.com/ticket/3189)
// Returns truly value when dom was changed, falsy otherwise.
function fixDom( evt ) {
var editor = evt.editor,
}
// When we're in block enter mode, a new paragraph will be established
- // to encapsulate inline contents inside editable. (#3657)
+ // to encapsulate inline contents inside editable. (http://dev.ckeditor.com/ticket/3657)
// Don't autoparagraph if browser (namely - IE) incorrectly anchored selection
// inside non-editable content. This happens e.g. if non-editable block is the only
// content of editable.
selectionUpdateNeeded = 1;
- // Cancel this selection change in favor of the next (correct). (#6811)
+ // Cancel this selection change in favor of the next (correct). (http://dev.ckeditor.com/ticket/6811)
evt.cancel();
}
}
if ( selection.isFake )
return 0;
- // Ensure bogus br could help to move cursor (out of styles) to the end of block. (#7041)
+ // Ensure bogus br could help to move cursor (out of styles) to the end of block. (http://dev.ckeditor.com/ticket/7041)
var pathBlock = path.block || path.blockLimit,
lastNode = pathBlock && pathBlock.getLast( isNotEmpty );
// Check some specialities of the current path block:
- // 1. It is really displayed as block; (#7221)
- // 2. It doesn't end with one inner block; (#7467)
+ // 1. It is really displayed as block; (http://dev.ckeditor.com/ticket/7221)
+ // 2. It doesn't end with one inner block; (http://dev.ckeditor.com/ticket/7467)
// 3. It doesn't have bogus br yet.
if (
pathBlock && pathBlock.isBlockBoundary() &&
// Whether in given context (pathBlock, pathBlockLimit and editor settings)
// editor should automatically wrap inline contents with blocks.
function shouldAutoParagraph( editor, pathBlock, pathBlockLimit ) {
- // Check whether pathBlock equals pathBlockLimit to support nested editable (#12162).
+ // Check whether pathBlock equals pathBlockLimit to support nested editable (http://dev.ckeditor.com/ticket/12162).
return editor.config.autoParagraph !== false &&
editor.activeEnterMode != CKEDITOR.ENTER_BR &&
(
// Select range and stop execution.
// If data has been totally emptied after the filtering,
- // any insertion is pointless (#10339).
+ // any insertion is pointless (http://dev.ckeditor.com/ticket/10339).
if ( data && processDataForInsertion( that, data ) ) {
// DATA INSERTION
insertDataIntoRange( that );
nodeName = node.getName();
// Extract only the list items, when insertion happens
- // inside of a list, reads as rearrange list items. (#7957)
+ // inside of a list, reads as rearrange list items. (http://dev.ckeditor.com/ticket/7957)
if ( insideOfList && nodeName in CKEDITOR.dtd.$list ) {
nodesData = nodesData.concat( extractNodesData( node, that ) );
continue;
}
// Don't use String.replace because it fails in IE7 if special replacement
- // characters ($$, $&, etc.) are in data (#10367).
+ // characters ($$, $&, etc.) are in data (http://dev.ckeditor.com/ticket/10367).
return wrapper.getOuterHtml().split( '{cke-peak}' ).join( data );
}
if ( ( bogus = startBlock.getBogus() ) )
bogus.remove();
- // Changing end container to element from text node (#12503).
+ // Changing end container to element from text node (http://dev.ckeditor.com/ticket/12503).
range.enlarge( CKEDITOR.ENLARGE_INLINE );
// Delete range contents. Do NOT merge. Merging is weird.
range = editor.getSelection().getRanges()[ 0 ];
range.collapse( 1 );
- // Optimizing range containers from text nodes to elements (#12503).
+ // Optimizing range containers from text nodes to elements (http://dev.ckeditor.com/ticket/12503).
range.optimize();
if ( range.startContainer.getHtml() === '' ) {
range.startContainer.appendBogus();
while ( ( next = endBookmark.getNext() ) ) {
next.insertAfter( startBookmark );
- // Update startBookmark after insertion to avoid the reversal of nodes (#13449).
+ // Update startBookmark after insertion to avoid the reversal of nodes (http://dev.ckeditor.com/ticket/13449).
startBookmark = next;
}
walker.guard = function( node, leaving ) {
// Guard may be executed on some node boundaries multiple times,
- // what results in creating more than one range for each selected cell. (#12964)
+ // what results in creating more than one range for each selected cell. (http://dev.ckeditor.com/ticket/12964)
if ( node.type == CKEDITOR.NODE_ELEMENT ) {
var key = 'visited_' + ( leaving ? 'out' : 'in' );
if ( node.getCustomData( key ) ) {