.../ckeditor/js/plugins/drupalimage/plugin.js | 69 ++++++++++---------- .../js/plugins/drupalimagecaption/plugin.js | 22 +++++++ .../js/plugins/drupalimagecaption/theme.js | 4 ++ .../lib/Drupal/editor/Form/EditorImageDialog.php | 34 ++++++---- 4 files changed, 85 insertions(+), 44 deletions(-) diff --git a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js index bf57f0f..7721ff2 100644 --- a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js +++ b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js @@ -18,8 +18,40 @@ CKEDITOR.plugins.add('drupalimage', { exec: function (editor, override) { var imageDOMElement = null; var existingValues = {}; - var saveCallback = null; var dialogTitle; + var saveCallback = function (returnValues) { + var selection = editor.getSelection(); + var imageElement = selection.getSelectedElement(); + + // Save snapshot for undo support. + editor.fire('saveSnapshot'); + + // Create a new image element if needed. + if (!imageElement && returnValues.attributes.src) { + imageElement = editor.document.createElement('img'); + imageElement.setAttribute('alt', ''); + editor.insertElement(imageElement); + } + // Delete the image if the src was removed. + if (imageElement && !returnValues.attributes.src) { + imageElement.remove(); + } + // Update the image properties. + else { + for (var key in returnValues.attributes) { + if (returnValues.attributes.hasOwnProperty(key)) { + // Update the property if a value is specified. + if (returnValues.attributes[key].length > 0) { + imageElement.setAttribute(key, returnValues.attributes[key]); + } + // Delete the property if set to an empty string. + else { + imageElement.removeAttribute(key); + } + } + } + } + }; // Allow CKEditor Widget plugins to execute DrupalImage's 'drupalimage' // command. In this case, they need to provide the DOM element for the @@ -30,8 +62,10 @@ CKEDITOR.plugins.add('drupalimage', { if (override) { imageDOMElement = override.imageDOMElement; existingValues = override.existingValues; - saveCallback = override.saveCallback; dialogTitle = override.dialogTitle; + if (override.saveCallback) { + saveCallback = override.saveCallback; + } } // Otherwise, retrieve the selected image and allow it to be edited, or // if no image is selected: insert a new one. @@ -71,37 +105,6 @@ CKEDITOR.plugins.add('drupalimage', { return; } } - - saveCallback = function (returnValues) { - // Save snapshot for undo support. - editor.fire('saveSnapshot'); - - // Create a new image element if needed. - if (!imageElement && returnValues.attributes.src) { - imageElement = editor.document.createElement('img'); - imageElement.setAttribute('alt', ''); - editor.insertElement(imageElement); - } - // Delete the image if the src was removed. - if (imageElement && !returnValues.attributes.src) { - imageElement.remove(); - } - // Update the image properties. - else { - for (var key in returnValues.attributes) { - if (returnValues.attributes.hasOwnProperty(key)) { - // Update the property if a value is specified. - if (returnValues.attributes[key].length > 0) { - imageElement.setAttribute(key, returnValues.attributes[key]); - } - // Delete the property if set to an empty string. - else { - imageElement.removeAttribute(key); - } - } - } - } - }; } // Drupal.t() will not work inside CKEditor plugins because CKEditor diff --git a/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js b/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js index b5fae0b..6a4b320 100644 --- a/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js +++ b/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js @@ -95,6 +95,24 @@ CKEDITOR.plugins.add('drupalimagecaption', { } }, + _selectionWillCreateInlineImage: function () { + // Returns node or first of its ancestors + // which is a block or block limit. + function getBlockParent( node, root ) { + var path = new CKEDITOR.dom.elementPath( node, root ); + return path.block || path.blockLimit; + } + + var range = editor.getSelection().getRanges()[ 0 ], + startEl = getBlockParent( range.startContainer, range.root ), + endEl = getBlockParent( range.endContainer, range.root ); + + var insideStartEl = range.checkBoundaryOfElement( startEl, CKEDITOR.START ); + var insideEndEl = range.checkBoundaryOfElement( endEl, CKEDITOR.END ); + + return !(insideStartEl && insideEndEl); + }, + _insertSaveCallback: function (returnValues) { // We can't create an image with an empty "src" attribute. if (returnValues.attributes.src.length === 0) { @@ -133,6 +151,10 @@ CKEDITOR.plugins.add('drupalimagecaption', { saveCallback: this._insertSaveCallback, dialogTitle: editor.config.drupalImage_dialogTitleAdd }; + if (this._selectionWillCreateInlineImage()) { + override.existingValues.isInline = this._selectionWillCreateInlineImage(); + delete override.saveCallback; + } editor.execCommand('drupalimage', override); }, diff --git a/core/modules/ckeditor/js/plugins/drupalimagecaption/theme.js b/core/modules/ckeditor/js/plugins/drupalimagecaption/theme.js index dd4c127..99384e9 100644 --- a/core/modules/ckeditor/js/plugins/drupalimagecaption/theme.js +++ b/core/modules/ckeditor/js/plugins/drupalimagecaption/theme.js @@ -197,6 +197,10 @@ CKEDITOR.on('instanceCreated', function (event) { saveCallback: saveCallback, dialogTitle: editor.config.drupalImage_dialogTitleAdd }; + if (this._selectionWillCreateInlineImage()) { + override.existingValues.isInline = this._selectionWillCreateInlineImage(); + delete override.saveCallback; + } editor.execCommand('drupalimage', override); }; }); diff --git a/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php b/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php index 2d8cc59..2abcf9a 100644 --- a/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php +++ b/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php @@ -92,17 +92,6 @@ public function buildForm(array $form, array &$form_state, FilterFormat $filter_ ); // When Drupal core's filter_caption is being used, the text editor may - // offer the ability to in-place edit the image's caption: show a toggle. - if (isset($input['hasCaption'])) { - $form['caption'] = array( - '#title' => t('Caption'), - '#type' => 'checkbox', - '#default_value' => $input['hasCaption'] === 'true', - '#parents' => array('hasCaption'), - ); - } - - // When Drupal core's filter_caption is being used, the text editor may // offer the ability to change the alignment. if (isset($input['data_align'])) { $form['align'] = array( @@ -121,6 +110,29 @@ public function buildForm(array $form, array &$form_state, FilterFormat $filter_ ); } + // When Drupal core's filter_caption is being used, the text editor may + // offer the ability to in-place edit the image's caption: show a toggle. + if (isset($input['hasCaption'])) { + $form['caption'] = array( + '#title' => t('Caption'), + '#type' => 'checkbox', + '#default_value' => $input['hasCaption'] === 'true', + '#parents' => array('hasCaption'), + ); + } + + $has_align_or_caption = isset($input['data_align']) || isset($input['hasCaption']); + if ($has_align_or_caption && isset($input['isInline']) && $input['isInline'] === 'true') { + $form['align']['#type'] = 'item'; + $form['align']['#description'] = t('Inline images cannot be aligned.'); + unset($form['align']['#default_value']); + + $form['caption']['#type'] = 'item'; + $form['caption']['#description'] = t('Inline images cannot be captioned.'); + $form['caption']['#wrapper_attributes'] = array('class' => array('container-inline')); + $form['caption']['#attributes'] = array('class' => array('container-inline')); + } + $form['actions'] = array( '#type' => 'actions', );