X-Git-Url: https://git.immae.eu/?p=perso%2FImmae%2FProjets%2Fpackagist%2Fludivine-ckeditor-component.git;a=blobdiff_plain;f=sources%2Fcore%2Feditor.js;h=640cec0b9720f739f412f4a478266a92b1abddc9;hp=8dfce7fed157f4eef0419ab22e178258358c65e3;hb=1794320dcfdfcd19572fb1676294f9853a6bbc20;hpb=7183f6a6a21ad9124e70c997e0168459f377a9f2 diff --git a/sources/core/editor.js b/sources/core/editor.js index 8dfce7f..640cec0 100644 --- a/sources/core/editor.js +++ b/sources/core/editor.js @@ -29,7 +29,7 @@ // Call the CKEDITOR.event constructor to initialize this instance. CKEDITOR.event.call( this ); - // Make a clone of the config object, to avoid having it touched by our code. (#9636) + // Make a clone of the config object, to avoid having it touched by our code. (http://dev.ckeditor.com/ticket/9636) instanceConfig = instanceConfig && CKEDITOR.tools.clone( instanceConfig ); // if editor is created off one page element. @@ -223,7 +223,7 @@ function updateCommandsContext( editor, path, forceRefresh ) { // Commands cannot be refreshed without a path. In edge cases // it may happen that there's no selection when this function is executed. - // For example when active filter is changed in #10877. + // For example when active filter is changed in http://dev.ckeditor.com/ticket/10877. if ( !path ) return; @@ -270,7 +270,7 @@ } else { // Load the custom configuration file. // To resolve customConfig race conflicts, use scriptLoader#queue - // instead of scriptLoader#load (#6504). + // instead of scriptLoader#load (http://dev.ckeditor.com/ticket/6504). CKEDITOR.scriptLoader.queue( customConfig, function() { // If the CKEDITOR.editorConfig function has been properly // defined in the custom configuration file, cache it. @@ -654,24 +654,49 @@ return editor.blockless ? CKEDITOR.ENTER_BR : enterMode; } - // Create DocumentFragment from specified ranges. For now it handles only tables in Firefox - // and returns DocumentFragment from the 1. range for other cases. (#13884) + // Create DocumentFragment from specified ranges. For now it handles only tables + // and returns DocumentFragment from the 1. range for other cases. (http://dev.ckeditor.com/ticket/13884) function createDocumentFragmentFromRanges( ranges, editable ) { var docFragment = new CKEDITOR.dom.documentFragment(), tableClone, currentRow, currentRowClone; + // We must handle two cases here: + // 1. [Cell] (IE9+, Edge, Chrome, Firefox) + // 2. [Cell] (IE8-, Safari) + function isSelectedCell( range ) { + var start = range.startContainer, + end = range.endContainer; + + if ( start.is && ( start.is( 'tr' ) || + ( start.is( 'td' ) && start.equals( end ) && range.endOffset === start.getChildCount() ) ) ) { + return true; + } + + return false; + } + + function cloneCell( range ) { + var start = range.startContainer; + + if ( start.is( 'tr' ) ) { + return range.cloneContents(); + } + + return start.clone( true ); + } + for ( var i = 0; i < ranges.length; i++ ) { var range = ranges[ i ], - container = range.startContainer; + container = range.startContainer.getAscendant( 'tr', true ); - if ( container.getName && container.getName() == 'tr' ) { + if ( isSelectedCell( range ) ) { if ( !tableClone ) { tableClone = container.getAscendant( 'table' ).clone(); - tableClone.append( container.getAscendant( 'tbody' ).clone() ); + tableClone.append( container.getAscendant( { thead: 1, tbody: 1, tfoot: 1 } ).clone() ); docFragment.append( tableClone ); - tableClone = tableClone.findOne( 'tbody' ); + tableClone = tableClone.findOne( 'thead, tbody, tfoot' ); } if ( !( currentRow && currentRow.equals( container ) ) ) { @@ -680,7 +705,7 @@ tableClone.append( currentRowClone ); } - currentRowClone.append( range.cloneContents() ); + currentRowClone.append( cloneCell( range ) ); } else { // If there was something else copied with table, // append it to DocumentFragment. @@ -717,7 +742,7 @@ // This guarantees that commands added before first editor#mode // aren't immediately updated, but waits for editor#mode and that // commands added later are immediately refreshed, even when added - // before instanceReady. #10103, #10249 + // before instanceReady. http://dev.ckeditor.com/ticket/10103, http://dev.ckeditor.com/ticket/10249 if ( this.mode ) updateCommand( this, cmd ); @@ -761,7 +786,7 @@ } ); } - // Remove 'submit' events registered on form element before destroying.(#3988) + // Remove 'submit' events registered on form element before destroying.(http://dev.ckeditor.com/ticket/3988) editor.on( 'destroy', function() { form.removeListener( 'submit', onSubmit ); } ); @@ -771,7 +796,7 @@ function onSubmit( evt ) { editor.updateElement(); - // #8031 If textarea had required attribute and editor is empty fire 'required' event and if + // http://dev.ckeditor.com/ticket/8031 If textarea had required attribute and editor is empty fire 'required' event and if // it was cancelled, prevent submitting the form. if ( editor._.required && !element.getValue() && editor.fire( 'required' ) === false ) { // When user press save button event (evt) is undefined (see save plugin). @@ -860,10 +885,10 @@ * * editorInstance.execCommand( 'bold' ); * - * @param {String} commandName The indentifier name of the command. - * @param {Object} [data] The data to be passed to the command. - * @returns {Boolean} `true` if the command was executed - * successfully, otherwise `false`. + * @param {String} commandName The identifier name of the command. + * @param {Object} [data] The data to be passed to the command. It defaults to + * an empty object starting from 4.7.0. + * @returns {Boolean} `true` if the command was executed successfully, `false` otherwise. * @see CKEDITOR.editor#addCommand */ execCommand: function( commandName, data ) { @@ -871,7 +896,7 @@ var eventData = { name: commandName, - commandData: data, + commandData: data || {}, command: command }; @@ -967,7 +992,7 @@ } else { // If we don't have a proper element, set data to an empty string, - // as this method is expected to return a string. (#13385) + // as this method is expected to return a string. (http://dev.ckeditor.com/ticket/13385) data = ''; } } @@ -1069,7 +1094,7 @@ this.readOnly = isReadOnly; // Block or release BACKSPACE key according to current read-only - // state to prevent browser's history navigation (#9761). + // state to prevent browser's history navigation (http://dev.ckeditor.com/ticket/9761). this.keystrokeHandler.blockedKeystrokes[ 8 ] = +isReadOnly; this.editable().setReadOnly( isReadOnly ); @@ -1198,17 +1223,20 @@ */ extractSelectedHtml: function( toString, removeEmptyBlock ) { var editable = this.editable(), - ranges = this.getSelection().getRanges(); + ranges = this.getSelection().getRanges(), + docFragment = new CKEDITOR.dom.documentFragment(), + i; if ( !editable || ranges.length === 0 ) { return null; } - var range = ranges[ 0 ], - docFragment = editable.extractHtmlFromRange( range, removeEmptyBlock ); + for ( i = 0; i < ranges.length; i++ ) { + docFragment.append( editable.extractHtmlFromRange( ranges[ i ], removeEmptyBlock ) ); + } if ( !removeEmptyBlock ) { - this.getSelection().selectRanges( [ range ] ); + this.getSelection().selectRanges( [ ranges[ 0 ] ] ); } return toString ? docFragment.getHtml() : docFragment; @@ -1325,28 +1353,33 @@ /** * Returns the keystroke that is assigned to a specified {@link CKEDITOR.command}. If no keystroke is assigned, - * it returns null. + * it returns `null`. + * + * Since version 4.7.0 this function also accepts a `command` parameter as a string. * * @since 4.6.0 - * @param {CKEDITOR.command} command - * @returns {Number} The keystroke assigned to the provided command or null if there is no keystroke. + * @param {CKEDITOR.command/String} command The {@link CKEDITOR.command} instance or a string with the command name. + * @returns {Number/null} The keystroke assigned to the provided command or `null` if there is no keystroke. */ getCommandKeystroke: function( command ) { - var commandName = command.name, - keystrokes = this.keystrokeHandler.keystrokes, - key; + var commandInstance = ( typeof command === 'string' ? this.getCommand( command ) : command ); - // Some commands have a fake keystroke - for example CUT/COPY/PASTE commands are handled natively. - if ( command.fakeKeystroke ) { - return command.fakeKeystroke; - } + if ( commandInstance ) { + var commandName = CKEDITOR.tools.object.findKey( this.commands, commandInstance ), + keystrokes = this.keystrokeHandler.keystrokes, + key; - for ( key in keystrokes ) { - if ( keystrokes.hasOwnProperty( key ) && keystrokes[ key ] == commandName ) { - return key; + // Some commands have a fake keystroke - for example CUT/COPY/PASTE commands are handled natively. + if ( commandInstance.fakeKeystroke ) { + return commandInstance.fakeKeystroke; } - } + for ( key in keystrokes ) { + if ( keystrokes.hasOwnProperty( key ) && keystrokes[ key ] == commandName ) { + return key; + } + } + } return null; }, @@ -1539,7 +1572,7 @@ CKEDITOR.ELEMENT_MODE_INLINE = 3; * @member CKEDITOR.config */ - /** +/** * Customizes the {@link CKEDITOR.editor#title human-readable title} of this editor. This title is displayed in * tooltips and impacts various [accessibility aspects](#!/guide/dev_a11y-section-announcing-the-editor-on-the-page), * e.g. it is commonly used by screen readers for distinguishing editor instances and for navigation.