Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ckeditor/ckeditor5-widget

Package Overview
Dependencies
Maintainers
1
Versions
703
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ckeditor/ckeditor5-widget - npm Package Compare versions

Comparing version 10.3.1 to 11.0.0

22

CHANGELOG.md
Changelog
=========
## [11.0.0](https://github.com/ckeditor/ckeditor5-widget/compare/v10.3.1...v11.0.0) (2019-02-28)
### Bug fixes
* Editor crashes after <kbd>Enter</kbd> key on an image that is inside a blockquote. Closes [ckeditor/ckeditor5#1555](https://github.com/ckeditor/ckeditor5/issues/1555). ([8a8842b](https://github.com/ckeditor/ckeditor5-widget/commit/8a8842b))
* Ensured only the widget toolbar attached to the view element which is deepest in the view tree will show up. Code and documentation refactoring in the `WidgetToolbarRepository`. Closes [#60](https://github.com/ckeditor/ckeditor5-widget/issues/60). ([7e11a24](https://github.com/ckeditor/ckeditor5-widget/commit/7e11a24))
* Make widget in editable clickable. Closes [ckeditor/ckeditor5-table#98](https://github.com/ckeditor/ckeditor5-table/issues/98). ([8226829](https://github.com/ckeditor/ckeditor5-widget/commit/8226829))
* Pressing <kbd>Enter</kbd> should split parent element when the inline widget is inside a `$block`. Closes [ckeditor/ckeditor5#1529](https://github.com/ckeditor/ckeditor5/issues/1529). ([847d2ab](https://github.com/ckeditor/ckeditor5-widget/commit/847d2ab))
* Fixed memory leaks during editor initialization and destruction (see [ckeditor/ckeditor5#1341](https://github.com/ckeditor/ckeditor5/issues/1341)). ([2e8f20d](https://github.com/ckeditor/ckeditor5-widget/commit/2e8f20d))
### Other changes
* Introduce support and utils for creating inline widgets. Closes [[ckeditor/ckeditor5#1096](https://github.com/ckeditor/ckeditor5/issues/1096)](https://github.com/ckeditor/ckeditor5/issues/1096). ([38fa159](https://github.com/ckeditor/ckeditor5-widget/commit/38fa159))
* Renamed the `.ck-widget_selectable` class to `.ck-widget_with-selection-handler` for better semantics. Closes [#66](https://github.com/ckeditor/ckeditor5-widget/issues/66). ([178ad5f](https://github.com/ckeditor/ckeditor5-widget/commit/178ad5f))
### BREAKING CHANGES
* Upgraded minimal versions of Node to `8.0.0` and npm to `5.7.1`. See: [ckeditor/ckeditor5#1507](https://github.com/ckeditor/ckeditor5/issues/1507). ([612ea3c](https://github.com/ckeditor/ckeditor5-cloud-services/commit/612ea3c))
* The `.ck-widget_selectable` class has been renamed to `.ck-widget_with-selection-handler` for better semantics.
* The `visibleWhen()` function, a property of an object passed into `WidgetToolbarRepository.register()`, has been renamed to `getRelatedElement()` and must return an editing `View` element the toolbar should be attached to (instead of `Boolean`).
## [10.3.1](https://github.com/ckeditor/ckeditor5-widget/compare/v10.3.0...v10.3.1) (2018-12-05)

@@ -5,0 +27,0 @@

2

LICENSE.md

@@ -5,3 +5,3 @@ Software License Agreement

**CKEditor 5 widget API** – https://github.com/ckeditor/ckeditor5-image <br>
Copyright (c) 2003-2018, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
Copyright (c) 2003-2019, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.

@@ -8,0 +8,0 @@ Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).

{
"name": "@ckeditor/ckeditor5-widget",
"version": "10.3.1",
"version": "11.0.0",
"description": "Widget API for CKEditor 5.",

@@ -12,27 +12,32 @@ "keywords": [

"dependencies": {
"@ckeditor/ckeditor5-core": "^11.1.0",
"@ckeditor/ckeditor5-engine": "^12.0.0",
"@ckeditor/ckeditor5-theme-lark": "^12.0.0",
"@ckeditor/ckeditor5-ui": "^11.2.0",
"@ckeditor/ckeditor5-utils": "^11.1.0"
"@ckeditor/ckeditor5-core": "^12.0.0",
"@ckeditor/ckeditor5-engine": "^13.0.0",
"@ckeditor/ckeditor5-theme-lark": "^13.0.0",
"@ckeditor/ckeditor5-ui": "^12.0.0",
"@ckeditor/ckeditor5-utils": "^12.0.0"
},
"devDependencies": {
"@ckeditor/ckeditor5-basic-styles": "^10.1.0",
"@ckeditor/ckeditor5-editor-balloon": "^11.0.2",
"@ckeditor/ckeditor5-editor-classic": "^11.0.2",
"@ckeditor/ckeditor5-essentials": "^10.1.3",
"@ckeditor/ckeditor5-paragraph": "^10.0.4",
"@ckeditor/ckeditor5-typing": "^11.0.2",
"@ckeditor/ckeditor5-basic-styles": "^11.0.0",
"@ckeditor/ckeditor5-clipboard": "^11.0.0",
"@ckeditor/ckeditor5-editor-balloon": "^12.0.0",
"@ckeditor/ckeditor5-editor-classic": "^12.0.0",
"@ckeditor/ckeditor5-enter": "^11.0.0",
"@ckeditor/ckeditor5-essentials": "^11.0.0",
"@ckeditor/ckeditor5-heading": "^11.0.0",
"@ckeditor/ckeditor5-paragraph": "^11.0.0",
"@ckeditor/ckeditor5-table": "^12.0.0",
"@ckeditor/ckeditor5-typing": "^12.0.0",
"@ckeditor/ckeditor5-undo": "^11.0.0",
"eslint": "^5.5.0",
"eslint-config-ckeditor5": "^1.0.7",
"husky": "^0.14.3",
"eslint-config-ckeditor5": "^1.0.11",
"husky": "^1.3.1",
"lint-staged": "^7.0.0"
},
"engines": {
"node": ">=6.9.0",
"npm": ">=3.0.0"
"node": ">=8.0.0",
"npm": ">=5.7.1"
},
"author": "CKSource (http://cksource.com/)",
"license": "GPL-2.0-or-later",
"homepage": "https://ckeditor.com",
"homepage": "https://ckeditor.com/ckeditor-5",
"bugs": "https://github.com/ckeditor/ckeditor5-widget/issues",

@@ -49,4 +54,3 @@ "repository": {

"scripts": {
"lint": "eslint --quiet '**/*.js'",
"precommit": "lint-staged"
"lint": "eslint --quiet '**/*.js'"
},

@@ -61,3 +65,8 @@ "lint-staged": {

"packages/**"
]
],
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
}
/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.

@@ -20,3 +20,3 @@ */

* * if two highlights have same priority - sort by CSS class provided in
* {@link module:engine/conversion/downcast-converters~HighlightDescriptor}.
* {@link module:engine/conversion/downcasthelpers~HighlightDescriptor}.
*

@@ -37,3 +37,3 @@ * This way, highlight will be applied with the same rules it is applied on texts.

* @fires change:top
* @param {module:engine/conversion/downcast-converters~HighlightDescriptor} descriptor
* @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor
* @param {module:engine/view/downcastwriter~DowncastWriter} writer

@@ -88,3 +88,3 @@ */

* @private
* @param {module:engine/conversion/downcast-converters~HighlightDescriptor} descriptor
* @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor
*/

@@ -137,4 +137,4 @@ _insertDescriptor( descriptor ) {

//
// @param {module:engine/conversion/downcast-converters~HighlightDescriptor} a
// @param {module:engine/conversion/downcast-converters~HighlightDescriptor} b
// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} a
// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} b
// @returns {Boolean} Returns true if both descriptors are defined and have same priority and classes.

@@ -147,4 +147,4 @@ function compareDescriptors( a, b ) {

//
// @param {module:engine/conversion/downcast-converters~HighlightDescriptor} a
// @param {module:engine/conversion/downcast-converters~HighlightDescriptor} b
// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} a
// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} b
// @returns {Boolean}

@@ -162,3 +162,3 @@ function shouldABeBeforeB( a, b ) {

// Converts CSS classes passed with {@link module:engine/conversion/downcast-converters~HighlightDescriptor} to
// Converts CSS classes passed with {@link module:engine/conversion/downcasthelpers~HighlightDescriptor} to
// sorted string.

@@ -177,7 +177,7 @@ //

* @param {Object} data Additional information about the change.
* @param {module:engine/conversion/downcast-converters~HighlightDescriptor} [data.newDescriptor] New highlight
* @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} [data.newDescriptor] New highlight
* descriptor. It will be `undefined` when last descriptor is removed from the stack.
* @param {module:engine/conversion/downcast-converters~HighlightDescriptor} [data.oldDescriptor] Old highlight
* @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} [data.oldDescriptor] Old highlight
* descriptor. It will be `undefined` when first descriptor is added to the stack.
* @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that can be used to modify element.
*/
/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.

@@ -16,5 +16,2 @@ */

const widgetSymbol = Symbol( 'isWidget' );
const labelSymbol = Symbol( 'label' );
/**

@@ -45,5 +42,6 @@ * CSS class added to each widget element.

return !!node.getCustomProperty( widgetSymbol );
return !!node.getCustomProperty( 'widget' );
}
/* eslint-disable max-len */
/**

@@ -58,4 +56,5 @@ * Converts the given {@link module:engine/view/element~Element} to a widget in the following way:

*
* This function needs to be used in conjuction with {@link module:engine/conversion/downcast-converters downcast converters}
* like {@link module:engine/conversion/downcast-converters~downcastElementToElement `downcastElementToElement()`}.
* This function needs to be used in conjunction with
* {@link module:engine/conversion/downcasthelpers~DowncastHelpers downcast conversion helpers}
* like {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.
* Moreover, typically you will want to use `toWidget()` only for `editingDowncast`, while keeping the `dataDowncast` clean.

@@ -67,3 +66,3 @@ *

* editor.conversion.for( 'editingDowncast' )
* .add( downcastElementToElement( {
* .elementToElement( {
* model: 'widget',

@@ -75,6 +74,6 @@ * view: ( modelItem, writer ) => {

* }
* } ) );
* } );
*
* editor.conversion.for( 'dataDowncast' )
* .add( downcastElementToElement( {
* .elementToElement( {
* model: 'widget',

@@ -84,3 +83,3 @@ * view: ( modelItem, writer ) => {

* }
* } ) );
* } );
*

@@ -98,2 +97,3 @@ * See the full source code of the widget (with a nested editable) schema definition and converters in

*/
/* eslint-enable max-len */
export function toWidget( element, writer, options = {} ) {

@@ -107,3 +107,3 @@ // The selection on Edge behaves better when the whole editor contents is in a single contenteditable element.

writer.addClass( WIDGET_CLASS_NAME, element );
writer.setCustomProperty( widgetSymbol, true, element );
writer.setCustomProperty( 'widget', true, element );
element.getFillerOffset = getFillerOffset;

@@ -170,3 +170,3 @@

export function setLabel( element, labelOrCreator, writer ) {
writer.setCustomProperty( labelSymbol, labelOrCreator, element );
writer.setCustomProperty( 'widgetLabel', labelOrCreator, element );
}

@@ -181,3 +181,3 @@

export function getLabel( element ) {
const labelCreator = element.getCustomProperty( labelSymbol );
const labelCreator = element.getCustomProperty( 'widgetLabel' );

@@ -200,3 +200,3 @@ if ( !labelCreator ) {

* Similarly to {@link ~toWidget `toWidget()`} this function should be used in `dataDowncast` only and it is usually
* used together with {@link module:engine/conversion/downcast-converters~downcastElementToElement `downcastElementToElement()`}.
* used together with {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.
*

@@ -207,3 +207,3 @@ * For example, in order to convert a `<nested>` model element to `<div class="nested">` in the view, you can define

* editor.conversion.for( 'editingDowncast' )
* .add( downcastElementToElement( {
* .elementToElement( {
* model: 'nested',

@@ -215,6 +215,6 @@ * view: ( modelItem, writer ) => {

* }
* } ) );
* } );
*
* editor.conversion.for( 'dataDowncast' )
* .add( downcastElementToElement( {
* .elementToElement( {
* model: 'nested',

@@ -224,3 +224,3 @@ * view: ( modelItem, writer ) => {

* }
* } ) );
* } );
*

@@ -279,3 +279,3 @@ * See the full source code of the widget (with nested editable) schema definition and converters in

if ( selectedElement ) {
if ( selectedElement && model.schema.isBlock( selectedElement ) ) {
return model.createPositionAfter( selectedElement );

@@ -307,2 +307,61 @@ }

/**
* A util to be used in order to map view positions to correct model positions when implementing a widget
* which renders non-empty view element for an empty model element.
*
* For example:
*
* // Model:
* <placeholder type="name"></placeholder>
*
* // View:
* <span class="placeholder">name</span>
*
* In such case, view positions inside `<span>` cannot be correct mapped to the model (because the model element is empty).
* To handle mapping positions inside `<span class="placeholder">` to the model use this util as follows:
*
* editor.editing.mapper.on(
* 'viewToModelPosition',
* viewToModelPositionOutsideModelElement( model, viewElement => viewElement.hasClass( 'placeholder' ) )
* );
*
* The callback will try to map the view offset of selection to an expected model position.
*
* 1. When the position is at the end (or in the middle) of the inline widget:
*
* // View:
* <p>foo <span class="placeholder">name|</span> bar</p>
*
* // Model:
* <paragraph>foo <placeholder type="name"></placeholder>| bar</paragraph>
*
* 2. When the position is at the beginning of the inline widget:
*
* // View:
* <p>foo <span class="placeholder">|name</span> bar</p>
*
* // Model:
* <paragraph>foo |<placeholder type="name"></placeholder> bar</paragraph>
*
* @param {module:engine/model/model~Model} model Model instance on which the callback operates.
* @param {Function} viewElementMatcher Function that is passed a view element and should return `true` if the custom mapping
* should be applied to the given view element.
* @return {Function}
*/
export function viewToModelPositionOutsideModelElement( model, viewElementMatcher ) {
return ( evt, data ) => {
const { mapper, viewPosition } = data;
const viewParent = mapper.findMappedViewAncestor( viewPosition );
if ( !viewElementMatcher( viewParent ) ) {
return;
}
const modelParent = mapper.toModelElement( viewParent );
data.modelPosition = model.createPositionAt( modelParent, viewPosition.isAtStart ? 'before' : 'after' );
};
}
// Default filler offset function applied to all widget elements.

@@ -337,3 +396,3 @@ //

writer.insert( writer.createPositionAt( editable, 0 ), selectionHandler );
writer.addClass( [ 'ck-widget_selectable' ], editable );
writer.addClass( [ 'ck-widget_with-selection-handler' ], editable );
}
/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.

@@ -12,4 +12,4 @@ */

import MouseObserver from '@ckeditor/ckeditor5-engine/src/view/observer/mouseobserver';
import { isWidget, WIDGET_SELECTED_CLASS_NAME, getLabel } from './utils';
import { keyCodes, getCode, parseKeystroke } from '@ckeditor/ckeditor5-utils/src/keyboard';
import { getLabel, isWidget, WIDGET_SELECTED_CLASS_NAME } from './utils';
import { getCode, keyCodes, parseKeystroke } from '@ckeditor/ckeditor5-utils/src/keyboard';

@@ -25,7 +25,7 @@ import '../theme/widget.css';

*
* This plugin enables multiple behaiors required by the widgets:
* This plugin enables multiple behaviors required by widgets:
*
* * The model to view selection converter for the editing pipeline (it handles widget custom selection rendering).
* If a converted selection is wraps around a widget element, that selection is marked as
* {@link module:engine/view/selection~Selection#isFake fake}. Additionally, proper the `ck-widget_selected` CSS class
* If a converted selection wraps around a widget element, that selection is marked as
* {@link module:engine/view/selection~Selection#isFake fake}. Additionally, the `ck-widget_selected` CSS class
* is added to indicate that widget has been selected.

@@ -155,3 +155,3 @@ * * The mouse and keyboard events handling on and around widget elements.

const keyCode = domEventData.keyCode;
const isForward = keyCode == keyCodes.delete || keyCode == keyCodes.arrowdown || keyCode == keyCodes.arrowright;
const isForward = keyCode == keyCodes.arrowdown || keyCode == keyCodes.arrowright;
let wasHandled = false;

@@ -274,9 +274,18 @@

const modelSelection = model.document.selection;
const objectElement = modelSelection.getSelectedElement();
const selectedElement = modelSelection.getSelectedElement();
if ( objectElement && model.schema.isObject( objectElement ) ) {
if ( shouldInsertParagraph( selectedElement, model.schema ) ) {
model.change( writer => {
let position = writer.createPositionAt( selectedElement, isBackwards ? 'before' : 'after' );
const paragraph = writer.createElement( 'paragraph' );
writer.insert( paragraph, objectElement, isBackwards ? 'before' : 'after' );
// Split the parent when inside a block element.
// https://github.com/ckeditor/ckeditor5/issues/1529
if ( model.schema.isBlock( selectedElement.parent ) ) {
const paragraphLimit = model.schema.findAllowedParent( position, paragraph );
position = writer.split( position, paragraphLimit ).position;
}
writer.insert( paragraph, position );
writer.setSelection( paragraph, 'in' );

@@ -422,6 +431,11 @@ } );

while ( element ) {
if ( !!element && element.is( 'editableElement' ) && !element.is( 'rootElement' ) ) {
if ( element.is( 'editableElement' ) && !element.is( 'rootElement' ) ) {
return true;
}
// Click on nested widget should select it.
if ( isWidget( element ) ) {
return false;
}
element = element.parent;

@@ -445,1 +459,9 @@ }

}
// Checks if enter key should insert paragraph. This should be done only on elements of type object (excluding inline objects).
//
// @param {module:engine/model/element~Element} element And element to check.
// @param {module:engine/model/schema~Schema} schema
function shouldInsertParagraph( element, schema ) {
return element && schema.isObject( element ) && !schema.isInline( element );
}
/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.

@@ -36,3 +36,3 @@ */

* items: editor.config.get( 'image.toolbar' ),
* visibleWhen: viewSelection => isImageWidgetSelected( viewSelection )
* getRelatedElement: getSelectedImageWidget
* } );

@@ -62,6 +62,7 @@ * }

const editor = this.editor;
const balloonToolbar = editor.plugins.get( 'BalloonToolbar' );
// Disables the default balloon toolbar for all widgets.
if ( balloonToolbar ) {
if ( editor.plugins.has( 'BalloonToolbar' ) ) {
const balloonToolbar = editor.plugins.get( 'BalloonToolbar' );
this.listenTo( balloonToolbar, 'show', evt => {

@@ -75,8 +76,8 @@ if ( isWidgetSelected( editor.editing.view.document.selection ) ) {

/**
* A map of toolbars.
* A map of toolbar definitions.
*
* @protected
* @member {Map.<string,Object>} #_toolbars
* @member {Map.<String,module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition>} #_toolbarDefinitions
*/
this._toolbars = new Map();
this._toolbarDefinitions = new Map();

@@ -98,5 +99,13 @@ /**

destroy() {
super.destroy();
for ( const toolbarConfig of this._toolbarDefinitions.values() ) {
toolbarConfig.view.destroy();
}
}
/**
* Registers toolbar in the WidgetToolbarRepository. It renders it in the `ContextualBalloon` based on the value of the invoked
* `visibleWhen` function. Toolbar items are gathered from `items` array.
* `getRelatedElement` function. Toolbar items are gathered from `items` array.
* The balloon's CSS class is by default `ck-toolbar-container` and may be override with the `balloonClassName` option.

@@ -110,10 +119,10 @@ *

* @param {Array.<String>} options.items Array of toolbar items.
* @param {Function} options.visibleWhen Callback which specifies when the toolbar should be visible for the widget.
* @param {Function} options.getRelatedElement Callback which returns an element the toolbar should be attached to.
* @param {String} [options.balloonClassName='ck-toolbar-container'] CSS class for the widget balloon.
*/
register( toolbarId, { items, visibleWhen, balloonClassName = 'ck-toolbar-container' } ) {
register( toolbarId, { items, getRelatedElement, balloonClassName = 'ck-toolbar-container' } ) {
const editor = this.editor;
const toolbarView = new ToolbarView();
if ( this._toolbars.has( toolbarId ) ) {
if ( this._toolbarDefinitions.has( toolbarId ) ) {
/**

@@ -130,5 +139,5 @@ * Toolbar with the given id was already added.

this._toolbars.set( toolbarId, {
this._toolbarDefinitions.set( toolbarId, {
view: toolbarView,
visibleWhen,
getRelatedElement,
balloonClassName,

@@ -144,9 +153,29 @@ } );

_updateToolbarsVisibility() {
for ( const toolbar of this._toolbars.values() ) {
if ( !this.editor.ui.focusTracker.isFocused || !toolbar.visibleWhen( this.editor.editing.view.document.selection ) ) {
this._hideToolbar( toolbar );
let maxRelatedElementDepth = 0;
let deepestRelatedElement = null;
let deepestToolbarDefinition = null;
for ( const definition of this._toolbarDefinitions.values() ) {
const relatedElement = definition.getRelatedElement( this.editor.editing.view.document.selection );
if ( !this.editor.ui.focusTracker.isFocused || !relatedElement ) {
this._hideToolbar( definition );
} else {
this._showToolbar( toolbar );
const relatedElementDepth = relatedElement.getAncestors().length;
// Many toolbars can express willingness to be displayed but they do not know about
// each other. Figure out which toolbar is deepest in the view tree to decide which
// should be displayed. For instance, if a selected image is inside a table cell, display
// the ImageToolbar rather than the TableToolbar (#60).
if ( relatedElementDepth > maxRelatedElementDepth ) {
maxRelatedElementDepth = relatedElementDepth;
deepestRelatedElement = relatedElement;
deepestToolbarDefinition = definition;
}
}
}
if ( deepestToolbarDefinition ) {
this._showToolbar( deepestToolbarDefinition, deepestRelatedElement );
}
}

@@ -158,15 +187,15 @@

* @private
* @param {Object} toolbar
* @param {module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition} toolbarDefinition
*/
_hideToolbar( toolbar ) {
if ( !this._isToolbarVisible( toolbar ) ) {
_hideToolbar( toolbarDefinition ) {
if ( !this._isToolbarVisible( toolbarDefinition ) ) {
return;
}
this._balloon.remove( toolbar.view );
this._balloon.remove( toolbarDefinition.view );
}
/**
* Shows up the toolbar if the toolbar is not visible and repositions the toolbar's balloon when toolbar's
* view is the most top view in balloon stack.
* Shows up the toolbar if the toolbar is not visible.
* Otherwise, repositions the toolbar's balloon when toolbar's view is the most top view in balloon stack.
*

@@ -177,12 +206,13 @@ * It might happen here that the toolbar's view is under another view. Then do nothing as the other toolbar view

* @private
* @param {Object} toolbar
* @param {module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition} toolbarDefinition
* @param {module:engine/view/element~Element} relatedElement
*/
_showToolbar( toolbar ) {
if ( this._isToolbarVisible( toolbar ) ) {
repositionContextualBalloon( this.editor );
} else if ( !this._balloon.hasView( toolbar.view ) ) {
_showToolbar( toolbarDefinition, relatedElement ) {
if ( this._isToolbarVisible( toolbarDefinition ) ) {
repositionContextualBalloon( this.editor, relatedElement );
} else if ( !this._balloon.hasView( toolbarDefinition.view ) ) {
this._balloon.add( {
view: toolbar.view,
position: getBalloonPositionData( this.editor ),
balloonClassName: toolbar.balloonClassName,
view: toolbarDefinition.view,
position: getBalloonPositionData( this.editor, relatedElement ),
balloonClassName: toolbarDefinition.balloonClassName,
} );

@@ -201,5 +231,5 @@ }

function repositionContextualBalloon( editor ) {
function repositionContextualBalloon( editor, relatedElement ) {
const balloon = editor.plugins.get( 'ContextualBalloon' );
const position = getBalloonPositionData( editor );
const position = getBalloonPositionData( editor, relatedElement );

@@ -209,9 +239,8 @@ balloon.updatePosition( position );

function getBalloonPositionData( editor ) {
function getBalloonPositionData( editor, relatedElement ) {
const editingView = editor.editing.view;
const defaultPositions = BalloonPanelView.defaultPositions;
const widget = getParentWidget( editingView.document.selection );
return {
target: editingView.domConverter.viewToDom( widget ),
target: editingView.domConverter.viewToDom( relatedElement ),
positions: [

@@ -228,21 +257,2 @@ defaultPositions.northArrowSouth,

function getParentWidget( selection ) {
const selectedElement = selection.getSelectedElement();
if ( selectedElement && isWidget( selectedElement ) ) {
return selectedElement;
}
const position = selection.getFirstPosition();
let parent = position.parent;
while ( parent ) {
if ( parent.is( 'element' ) && isWidget( parent ) ) {
return parent;
}
parent = parent.parent;
}
}
function isWidgetSelected( selection ) {

@@ -253,1 +263,16 @@ const viewElement = selection.getSelectedElement();

}
/**
* The toolbar definition object used by the toolbar repository to manage toolbars.
* It contains information necessary to display the toolbar in the
* {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} and
* update it during its life (display) cycle.
*
* @typedef {Object} module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition
*
* @property {module:ui/view~View} view The UI view of the toolbar.
* @property {Function} getRelatedElement A function that returns an engine {@link module:engine/view/view~View}
* element the toolbar is to be attached to. For instance, an image widget or a table widget (or `null` when
* there is no such element). The function accepts an instance of {@link module:engine/view/selection~Selection}.
* @property {String} balloonClassName CSS class for the widget balloon when a toolbar is displayed.
*/

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc