]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blobdiff - sources/core/editor.js
Update to 4.7.3
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / core / editor.js
index 8dfce7fed157f4eef0419ab22e178258358c65e3..640cec0b9720f739f412f4a478266a92b1abddc9 100644 (file)
@@ -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.
        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;
 
                } 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.
                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. <tr>[<td>Cell</td>]</tr> (IE9+, Edge, Chrome, Firefox)
+               // 2. <td>[Cell]</td> (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 ) ) ) {
                                        tableClone.append( currentRowClone );
                                }
 
-                               currentRowClone.append( range.cloneContents() );
+                               currentRowClone.append( cloneCell( range ) );
                        } else {
                                // If there was something else copied with table,
                                // append it to DocumentFragment.
                        // 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 );
 
                                                } );
                                        }
 
-                                       // 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 );
                                        } );
                        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).
                 *
                 *              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 ) {
 
                        var eventData = {
                                name: commandName,
-                               commandData: data,
+                               commandData: data || {},
                                command: command
                        };
 
                                }
                                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 = '';
                                }
                        }
                                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 );
                 */
                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;
 
                /**
                 * 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.