X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FProjets%2Fpackagist%2Fludivine-ckeditor-component.git;a=blobdiff_plain;f=sources%2Fcore%2Feditable.js;h=6b3fa9f7d7e64c4454d9a02e3e8fb3009b912bf3;hp=c50ec7fe80e0bb37d06a958f26c70a3492e4934a;hb=1794320dcfdfcd19572fb1676294f9853a6bbc20;hpb=7183f6a6a21ad9124e70c997e0168459f377a9f2 diff --git a/sources/core/editable.js b/sources/core/editable.js index c50ec7f..6b3fa9f 100644 --- a/sources/core/editable.js +++ b/sources/core/editable.js @@ -76,7 +76,7 @@ // [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; } @@ -87,7 +87,15 @@ 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. @@ -95,7 +103,7 @@ 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() ) ) @@ -117,7 +125,7 @@ // 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; @@ -252,7 +260,7 @@ * @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' ); }, @@ -350,7 +358,7 @@ 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' ); @@ -363,12 +371,12 @@ 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 ) { @@ -456,7 +464,7 @@ 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 ); @@ -770,7 +778,7 @@ 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(); @@ -832,7 +840,7 @@ // 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; @@ -884,14 +892,14 @@ }, 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() { @@ -967,7 +975,7 @@ // 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; @@ -980,7 +988,7 @@ 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; @@ -990,10 +998,15 @@ 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, @@ -1001,16 +1014,17 @@ 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(); @@ -1020,7 +1034,7 @@ 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 ) && @@ -1095,28 +1109,28 @@ 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(); @@ -1127,7 +1141,7 @@ } // 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 ) { @@ -1158,7 +1172,7 @@ } // 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 ) { @@ -1172,8 +1186,14 @@ 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 ) { @@ -1184,7 +1204,7 @@ 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' ); @@ -1241,6 +1261,7 @@ * @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; @@ -1263,7 +1284,7 @@ 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' ) ) ) { @@ -1278,9 +1299,9 @@ 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(); @@ -1330,7 +1351,7 @@ } ); } ); - // #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}' ); @@ -1347,8 +1368,8 @@ // Matching an empty paragraph at the end of document. emptyParagraphRegexp = /(^|]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:]*>| |\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, @@ -1369,7 +1390,7 @@ } // 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. @@ -1397,7 +1418,7 @@ 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(); } } @@ -1413,13 +1434,13 @@ 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() && @@ -1556,7 +1577,7 @@ // 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 && ( @@ -1623,7 +1644,7 @@ // 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 ); @@ -2008,7 +2029,7 @@ 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; @@ -2256,7 +2277,7 @@ } // 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 ); } @@ -2517,7 +2538,7 @@ 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. @@ -2540,7 +2561,7 @@ 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(); @@ -2762,7 +2783,7 @@ 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; } @@ -2913,7 +2934,7 @@ 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 ) ) {