{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-link/src/linkui.js"],"names":["VISUAL_SELECTION_MARKER_NAME","LinkUI","editor","this","editing","view","addObserver","ClickObserver","actionsView","_createActionsView","formView","_createFormView","_balloon","plugins","get","ContextualBalloon","_createToolbarLinkButton","_enableUserBalloonInteractions","conversion","for","markerToHighlight","model","classes","markerToElement","name","Object","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_get_js__WEBPACK_IMPORTED_MODULE_6__","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_getPrototypeOf_js__WEBPACK_IMPORTED_MODULE_9__","prototype","call","destroy","_this","LinkActionsView","locale","linkCommand","commands","unlinkCommand","bind","to","editButtonView","unlinkButtonView","listenTo","_addFormView","execute","_hideUI","keystrokes","set","data","cancel","LINK_KEYSTROKE","_this2","defaultProtocol","config","LinkFormView","urlInputView","fieldView","value","saveButtonView","element","parsedUrl","addLinkProtocolIfApplicable","getDecoratorSwitchesState","_closeFormView","_this3","t","keyEvtData","isEnabled","_showUI","ui","componentFactory","add","button","ButtonView","label","icon","linkIcon","keystroke","tooltip","isToggleable","_this4","viewDocument","document","parentLink","_getSelectedLinkElement","_areActionsVisible","focusTracker","isFocused","focus","priority","_isUIVisible","clickOutsideHandler","emitter","activator","_isUIInPanel","contextElements","callback","_areActionsInPanel","position","_getBalloonPositionData","_isFormInPanel","disableCssTransitions","visibleView","select","enableCssTransitions","restoreManualDecoratorStates","undefined","_removeFormView","remove","_hideFakeVisualSelection","forceVisible","arguments","length","_addActionsView","showStack","_showFakeVisualSelection","_startUpdatingUI","stopListening","_this5","prevSelectedLink","prevSelectionParent","getSelectionParent","update","selectedLink","selectionParent","updatePosition","selection","getAncestors","reverse","find","node","is","hasView","_this6","target","markers","has","markerViewElements","Array","from","mapper","markerNameToElements","newRange","createRange","createPositionBefore","createPositionAfter","domConverter","viewRangeToDom","targetLink","mapViewToDom","getFirstRange","selectedElement","getSelectedElement","isCollapsed","isWidget","findLinkElementAncestor","getFirstPosition","range","getTrimmed","startLink","start","endLink","end","createRangeIn","isEqual","change","writer","updateMarker","isAtEnd","startPosition","getLastMatchingPosition","_ref","item","schema","isContent","boundaries","addMarker","usingOperation","affectsData","removeMarker","Plugin","ancestor","isLinkElement"],"mappings":"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","file":"js/chunk-2d0deae7.799c8645.js","sourcesContent":["/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/linkui\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport { ClickObserver } from 'ckeditor5/src/engine';\nimport { ButtonView, ContextualBalloon, clickOutsideHandler } from 'ckeditor5/src/ui';\nimport { isWidget } from 'ckeditor5/src/widget';\nimport LinkFormView from './ui/linkformview';\nimport LinkActionsView from './ui/linkactionsview';\nimport { addLinkProtocolIfApplicable, isLinkElement, LINK_KEYSTROKE } from './utils';\n\nimport linkIcon from '../theme/icons/link.svg';\n\nconst VISUAL_SELECTION_MARKER_NAME = 'link-ui';\n\n/**\n * The link UI plugin. It introduces the `'link'` and `'unlink'` buttons and support for the Ctrl+K keystroke.\n *\n * It uses the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class LinkUI extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'LinkUI';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\teditor.editing.view.addObserver( ClickObserver );\n\n\t\t/**\n\t\t * The actions view displayed inside of the balloon.\n\t\t *\n\t\t * @member {module:link/ui/linkactionsview~LinkActionsView}\n\t\t */\n\t\tthis.actionsView = this._createActionsView();\n\n\t\t/**\n\t\t * The form view displayed inside the balloon.\n\t\t *\n\t\t * @member {module:link/ui/linkformview~LinkFormView}\n\t\t */\n\t\tthis.formView = this._createFormView();\n\n\t\t/**\n\t\t * The contextual balloon plugin instance.\n\t\t *\n\t\t * @private\n\t\t * @member {module:ui/panel/balloon/contextualballoon~ContextualBalloon}\n\t\t */\n\t\tthis._balloon = editor.plugins.get( ContextualBalloon );\n\n\t\t// Create toolbar buttons.\n\t\tthis._createToolbarLinkButton();\n\n\t\t// Attach lifecycle actions to the the balloon.\n\t\tthis._enableUserBalloonInteractions();\n\n\t\t// Renders a fake visual selection marker on an expanded selection.\n\t\teditor.conversion.for( 'editingDowncast' ).markerToHighlight( {\n\t\t\tmodel: VISUAL_SELECTION_MARKER_NAME,\n\t\t\tview: {\n\t\t\t\tclasses: [ 'ck-fake-link-selection' ]\n\t\t\t}\n\t\t} );\n\n\t\t// Renders a fake visual selection marker on a collapsed selection.\n\t\teditor.conversion.for( 'editingDowncast' ).markerToElement( {\n\t\t\tmodel: VISUAL_SELECTION_MARKER_NAME,\n\t\t\tview: {\n\t\t\t\tname: 'span',\n\t\t\t\tclasses: [ 'ck-fake-link-selection', 'ck-fake-link-selection_collapsed' ]\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\t// Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).\n\t\tthis.formView.destroy();\n\t}\n\n\t/**\n\t * Creates the {@link module:link/ui/linkactionsview~LinkActionsView} instance.\n\t *\n\t * @private\n\t * @returns {module:link/ui/linkactionsview~LinkActionsView} The link actions view instance.\n\t */\n\t_createActionsView() {\n\t\tconst editor = this.editor;\n\t\tconst actionsView = new LinkActionsView( editor.locale );\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\t\tconst unlinkCommand = editor.commands.get( 'unlink' );\n\n\t\tactionsView.bind( 'href' ).to( linkCommand, 'value' );\n\t\tactionsView.editButtonView.bind( 'isEnabled' ).to( linkCommand );\n\t\tactionsView.unlinkButtonView.bind( 'isEnabled' ).to( unlinkCommand );\n\n\t\t// Execute unlink command after clicking on the \"Edit\" button.\n\t\tthis.listenTo( actionsView, 'edit', () => {\n\t\t\tthis._addFormView();\n\t\t} );\n\n\t\t// Execute unlink command after clicking on the \"Unlink\" button.\n\t\tthis.listenTo( actionsView, 'unlink', () => {\n\t\t\teditor.execute( 'unlink' );\n\t\t\tthis._hideUI();\n\t\t} );\n\n\t\t// Close the panel on esc key press when the **actions have focus**.\n\t\tactionsView.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\t\tthis._hideUI();\n\t\t\tcancel();\n\t\t} );\n\n\t\t// Open the form view on Ctrl+K when the **actions have focus**..\n\t\tactionsView.keystrokes.set( LINK_KEYSTROKE, ( data, cancel ) => {\n\t\t\tthis._addFormView();\n\t\t\tcancel();\n\t\t} );\n\n\t\treturn actionsView;\n\t}\n\n\t/**\n\t * Creates the {@link module:link/ui/linkformview~LinkFormView} instance.\n\t *\n\t * @private\n\t * @returns {module:link/ui/linkformview~LinkFormView} The link form view instance.\n\t */\n\t_createFormView() {\n\t\tconst editor = this.editor;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\t\tconst defaultProtocol = editor.config.get( 'link.defaultProtocol' );\n\n\t\tconst formView = new LinkFormView( editor.locale, linkCommand );\n\n\t\tformView.urlInputView.fieldView.bind( 'value' ).to( linkCommand, 'value' );\n\n\t\t// Form elements should be read-only when corresponding commands are disabled.\n\t\tformView.urlInputView.bind( 'isReadOnly' ).to( linkCommand, 'isEnabled', value => !value );\n\t\tformView.saveButtonView.bind( 'isEnabled' ).to( linkCommand );\n\n\t\t// Execute link command after clicking the \"Save\" button.\n\t\tthis.listenTo( formView, 'submit', () => {\n\t\t\tconst { value } = formView.urlInputView.fieldView.element;\n\t\t\tconst parsedUrl = addLinkProtocolIfApplicable( value, defaultProtocol );\n\t\t\teditor.execute( 'link', parsedUrl, formView.getDecoratorSwitchesState() );\n\t\t\tthis._closeFormView();\n\t\t} );\n\n\t\t// Hide the panel after clicking the \"Cancel\" button.\n\t\tthis.listenTo( formView, 'cancel', () => {\n\t\t\tthis._closeFormView();\n\t\t} );\n\n\t\t// Close the panel on esc key press when the **form has focus**.\n\t\tformView.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\t\tthis._closeFormView();\n\t\t\tcancel();\n\t\t} );\n\n\t\treturn formView;\n\t}\n\n\t/**\n\t * Creates a toolbar Link button. Clicking this button will show\n\t * a {@link #_balloon} attached to the selection.\n\t *\n\t * @private\n\t */\n\t_createToolbarLinkButton() {\n\t\tconst editor = this.editor;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\t\tconst t = editor.t;\n\n\t\t// Handle the `Ctrl+K` keystroke and show the panel.\n\t\teditor.keystrokes.set( LINK_KEYSTROKE, ( keyEvtData, cancel ) => {\n\t\t\t// Prevent focusing the search bar in FF, Chrome and Edge. See https://github.com/ckeditor/ckeditor5/issues/4811.\n\t\t\tcancel();\n\n\t\t\tif ( linkCommand.isEnabled ) {\n\t\t\t\tthis._showUI( true );\n\t\t\t}\n\t\t} );\n\n\t\teditor.ui.componentFactory.add( 'link', locale => {\n\t\t\tconst button = new ButtonView( locale );\n\n\t\t\tbutton.isEnabled = true;\n\t\t\tbutton.label = t( 'Link' );\n\t\t\tbutton.icon = linkIcon;\n\t\t\tbutton.keystroke = LINK_KEYSTROKE;\n\t\t\tbutton.tooltip = true;\n\t\t\tbutton.isToggleable = true;\n\n\t\t\t// Bind button to the command.\n\t\t\tbutton.bind( 'isEnabled' ).to( linkCommand, 'isEnabled' );\n\t\t\tbutton.bind( 'isOn' ).to( linkCommand, 'value', value => !!value );\n\n\t\t\t// Show the panel on button click.\n\t\t\tthis.listenTo( button, 'execute', () => this._showUI( true ) );\n\n\t\t\treturn button;\n\t\t} );\n\t}\n\n\t/**\n\t * Attaches actions that control whether the balloon panel containing the\n\t * {@link #formView} is visible or not.\n\t *\n\t * @private\n\t */\n\t_enableUserBalloonInteractions() {\n\t\tconst viewDocument = this.editor.editing.view.document;\n\n\t\t// Handle click on view document and show panel when selection is placed inside the link element.\n\t\t// Keep panel open until selection will be inside the same link element.\n\t\tthis.listenTo( viewDocument, 'click', () => {\n\t\t\tconst parentLink = this._getSelectedLinkElement();\n\n\t\t\tif ( parentLink ) {\n\t\t\t\t// Then show panel but keep focus inside editor editable.\n\t\t\t\tthis._showUI();\n\t\t\t}\n\t\t} );\n\n\t\t// Focus the form if the balloon is visible and the Tab key has been pressed.\n\t\tthis.editor.keystrokes.set( 'Tab', ( data, cancel ) => {\n\t\t\tif ( this._areActionsVisible && !this.actionsView.focusTracker.isFocused ) {\n\t\t\t\tthis.actionsView.focus();\n\t\t\t\tcancel();\n\t\t\t}\n\t\t}, {\n\t\t\t// Use the high priority because the link UI navigation is more important\n\t\t\t// than other feature's actions, e.g. list indentation.\n\t\t\t// https://github.com/ckeditor/ckeditor5-link/issues/146\n\t\t\tpriority: 'high'\n\t\t} );\n\n\t\t// Close the panel on the Esc key press when the editable has focus and the balloon is visible.\n\t\tthis.editor.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\t\tif ( this._isUIVisible ) {\n\t\t\t\tthis._hideUI();\n\t\t\t\tcancel();\n\t\t\t}\n\t\t} );\n\n\t\t// Close on click outside of balloon panel element.\n\t\tclickOutsideHandler( {\n\t\t\temitter: this.formView,\n\t\t\tactivator: () => this._isUIInPanel,\n\t\t\tcontextElements: [ this._balloon.view.element ],\n\t\t\tcallback: () => this._hideUI()\n\t\t} );\n\t}\n\n\t/**\n\t * Adds the {@link #actionsView} to the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n\t_addActionsView() {\n\t\tif ( this._areActionsInPanel ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._balloon.add( {\n\t\t\tview: this.actionsView,\n\t\t\tposition: this._getBalloonPositionData()\n\t\t} );\n\t}\n\n\t/**\n\t * Adds the {@link #formView} to the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n\t_addFormView() {\n\t\tif ( this._isFormInPanel ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.editor;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\n\t\tthis.formView.disableCssTransitions();\n\n\t\tthis._balloon.add( {\n\t\t\tview: this.formView,\n\t\t\tposition: this._getBalloonPositionData()\n\t\t} );\n\n\t\t// Select input when form view is currently visible.\n\t\tif ( this._balloon.visibleView === this.formView ) {\n\t\t\tthis.formView.urlInputView.fieldView.select();\n\t\t}\n\n\t\tthis.formView.enableCssTransitions();\n\n\t\t// Make sure that each time the panel shows up, the URL field remains in sync with the value of\n\t\t// the command. If the user typed in the input, then canceled the balloon (`urlInputView.fieldView#value` stays\n\t\t// unaltered) and re-opened it without changing the value of the link command (e.g. because they\n\t\t// clicked the same link), they would see the old value instead of the actual value of the command.\n\t\t// https://github.com/ckeditor/ckeditor5-link/issues/78\n\t\t// https://github.com/ckeditor/ckeditor5-link/issues/123\n\t\tthis.formView.urlInputView.fieldView.element.value = linkCommand.value || '';\n\t}\n\n\t/**\n\t * Closes the form view. Decides whether the balloon should be hidden completely or if the action view should be shown. This is\n\t * decided upon the link command value (which has a value if the document selection is in the link).\n\t *\n\t * Additionally, if any {@link module:link/link~LinkConfig#decorators} are defined in the editor configuration, the state of\n\t * switch buttons responsible for manual decorator handling is restored.\n\t *\n\t * @private\n\t */\n\t_closeFormView() {\n\t\tconst linkCommand = this.editor.commands.get( 'link' );\n\n\t\t// Restore manual decorator states to represent the current model state. This case is important to reset the switch buttons\n\t\t// when the user cancels the editing form.\n\t\tlinkCommand.restoreManualDecoratorStates();\n\n\t\tif ( linkCommand.value !== undefined ) {\n\t\t\tthis._removeFormView();\n\t\t} else {\n\t\t\tthis._hideUI();\n\t\t}\n\t}\n\n\t/**\n\t * Removes the {@link #formView} from the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n\t_removeFormView() {\n\t\tif ( this._isFormInPanel ) {\n\t\t\t// Blur the input element before removing it from DOM to prevent issues in some browsers.\n\t\t\t// See https://github.com/ckeditor/ckeditor5/issues/1501.\n\t\t\tthis.formView.saveButtonView.focus();\n\n\t\t\tthis._balloon.remove( this.formView );\n\n\t\t\t// Because the form has an input which has focus, the focus must be brought back\n\t\t\t// to the editor. Otherwise, it would be lost.\n\t\t\tthis.editor.editing.view.focus();\n\n\t\t\tthis._hideFakeVisualSelection();\n\t\t}\n\t}\n\n\t/**\n\t * Shows the correct UI type. It is either {@link #formView} or {@link #actionsView}.\n\t *\n\t * @param {Boolean} forceVisible\n\t * @private\n\t */\n\t_showUI( forceVisible = false ) {\n\t\t// When there's no link under the selection, go straight to the editing UI.\n\t\tif ( !this._getSelectedLinkElement() ) {\n\t\t\t// Show visual selection on a text without a link when the contextual balloon is displayed.\n\t\t\t// See https://github.com/ckeditor/ckeditor5/issues/4721.\n\t\t\tthis._showFakeVisualSelection();\n\n\t\t\tthis._addActionsView();\n\n\t\t\t// Be sure panel with link is visible.\n\t\t\tif ( forceVisible ) {\n\t\t\t\tthis._balloon.showStack( 'main' );\n\t\t\t}\n\n\t\t\tthis._addFormView();\n\t\t}\n\t\t// If there's a link under the selection...\n\t\telse {\n\t\t\t// Go to the editing UI if actions are already visible.\n\t\t\tif ( this._areActionsVisible ) {\n\t\t\t\tthis._addFormView();\n\t\t\t}\n\t\t\t// Otherwise display just the actions UI.\n\t\t\telse {\n\t\t\t\tthis._addActionsView();\n\t\t\t}\n\n\t\t\t// Be sure panel with link is visible.\n\t\t\tif ( forceVisible ) {\n\t\t\t\tthis._balloon.showStack( 'main' );\n\t\t\t}\n\t\t}\n\n\t\t// Begin responding to ui#update once the UI is added.\n\t\tthis._startUpdatingUI();\n\t}\n\n\t/**\n\t * Removes the {@link #formView} from the {@link #_balloon}.\n\t *\n\t * See {@link #_addFormView}, {@link #_addActionsView}.\n\t *\n\t * @protected\n\t */\n\t_hideUI() {\n\t\tif ( !this._isUIInPanel ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.editor;\n\n\t\tthis.stopListening( editor.ui, 'update' );\n\t\tthis.stopListening( this._balloon, 'change:visibleView' );\n\n\t\t// Make sure the focus always gets back to the editable _before_ removing the focused form view.\n\t\t// Doing otherwise causes issues in some browsers. See https://github.com/ckeditor/ckeditor5-link/issues/193.\n\t\teditor.editing.view.focus();\n\n\t\t// Remove form first because it's on top of the stack.\n\t\tthis._removeFormView();\n\n\t\t// Then remove the actions view because it's beneath the form.\n\t\tthis._balloon.remove( this.actionsView );\n\n\t\tthis._hideFakeVisualSelection();\n\t}\n\n\t/**\n\t * Makes the UI react to the {@link module:core/editor/editorui~EditorUI#event:update} event to\n\t * reposition itself when the editor UI should be refreshed.\n\t *\n\t * See: {@link #_hideUI} to learn when the UI stops reacting to the `update` event.\n\t *\n\t * @protected\n\t */\n\t_startUpdatingUI() {\n\t\tconst editor = this.editor;\n\t\tconst viewDocument = editor.editing.view.document;\n\n\t\tlet prevSelectedLink = this._getSelectedLinkElement();\n\t\tlet prevSelectionParent = getSelectionParent();\n\n\t\tconst update = () => {\n\t\t\tconst selectedLink = this._getSelectedLinkElement();\n\t\t\tconst selectionParent = getSelectionParent();\n\n\t\t\t// Hide the panel if:\n\t\t\t//\n\t\t\t// * the selection went out of the EXISTING link element. E.g. user moved the caret out\n\t\t\t// of the link,\n\t\t\t// * the selection went to a different parent when creating a NEW link. E.g. someone\n\t\t\t// else modified the document.\n\t\t\t// * the selection has expanded (e.g. displaying link actions then pressing SHIFT+Right arrow).\n\t\t\t//\n\t\t\t// Note: #_getSelectedLinkElement will return a link for a non-collapsed selection only\n\t\t\t// when fully selected.\n\t\t\tif ( ( prevSelectedLink && !selectedLink ) ||\n\t\t\t\t( !prevSelectedLink && selectionParent !== prevSelectionParent ) ) {\n\t\t\t\tthis._hideUI();\n\t\t\t}\n\t\t\t// Update the position of the panel when:\n\t\t\t// * link panel is in the visible stack\n\t\t\t// * the selection remains in the original link element,\n\t\t\t// * there was no link element in the first place, i.e. creating a new link\n\t\t\telse if ( this._isUIVisible ) {\n\t\t\t\t// If still in a link element, simply update the position of the balloon.\n\t\t\t\t// If there was no link (e.g. inserting one), the balloon must be moved\n\t\t\t\t// to the new position in the editing view (a new native DOM range).\n\t\t\t\tthis._balloon.updatePosition( this._getBalloonPositionData() );\n\t\t\t}\n\n\t\t\tprevSelectedLink = selectedLink;\n\t\t\tprevSelectionParent = selectionParent;\n\t\t};\n\n\t\tfunction getSelectionParent() {\n\t\t\treturn viewDocument.selection.focus.getAncestors()\n\t\t\t\t.reverse()\n\t\t\t\t.find( node => node.is( 'element' ) );\n\t\t}\n\n\t\tthis.listenTo( editor.ui, 'update', update );\n\t\tthis.listenTo( this._balloon, 'change:visibleView', update );\n\t}\n\n\t/**\n\t * Returns `true` when {@link #formView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _isFormInPanel() {\n\t\treturn this._balloon.hasView( this.formView );\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _areActionsInPanel() {\n\t\treturn this._balloon.hasView( this.actionsView );\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is\n\t * currently visible.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _areActionsVisible() {\n\t\treturn this._balloon.visibleView === this.actionsView;\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _isUIInPanel() {\n\t\treturn this._isFormInPanel || this._areActionsInPanel;\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is\n\t * currently visible.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _isUIVisible() {\n\t\tconst visibleView = this._balloon.visibleView;\n\n\t\treturn visibleView == this.formView || this._areActionsVisible;\n\t}\n\n\t/**\n\t * Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached\n\t * to the target element or selection.\n\t *\n\t * If the selection is collapsed and inside a link element, the panel will be attached to the\n\t * entire link element. Otherwise, it will be attached to the selection.\n\t *\n\t * @private\n\t * @returns {module:utils/dom/position~Options}\n\t */\n\t_getBalloonPositionData() {\n\t\tconst view = this.editor.editing.view;\n\t\tconst model = this.editor.model;\n\t\tconst viewDocument = view.document;\n\t\tlet target = null;\n\n\t\tif ( model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ) {\n\t\t\t// There are cases when we highlight selection using a marker (#7705, #4721).\n\t\t\tconst markerViewElements = Array.from( this.editor.editing.mapper.markerNameToElements( VISUAL_SELECTION_MARKER_NAME ) );\n\t\t\tconst newRange = view.createRange(\n\t\t\t\tview.createPositionBefore( markerViewElements[ 0 ] ),\n\t\t\t\tview.createPositionAfter( markerViewElements[ markerViewElements.length - 1 ] )\n\t\t\t);\n\n\t\t\ttarget = view.domConverter.viewRangeToDom( newRange );\n\t\t} else {\n\t\t\t// Make sure the target is calculated on demand at the last moment because a cached DOM range\n\t\t\t// (which is very fragile) can desynchronize with the state of the editing view if there was\n\t\t\t// any rendering done in the meantime. This can happen, for instance, when an inline widget\n\t\t\t// gets unlinked.\n\t\t\ttarget = () => {\n\t\t\t\tconst targetLink = this._getSelectedLinkElement();\n\n\t\t\t\treturn targetLink ?\n\t\t\t\t\t// When selection is inside link element, then attach panel to this element.\n\t\t\t\t\tview.domConverter.mapViewToDom( targetLink ) :\n\t\t\t\t\t// Otherwise attach panel to the selection.\n\t\t\t\t\tview.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() );\n\t\t\t};\n\t\t}\n\n\t\treturn { target };\n\t}\n\n\t/**\n\t * Returns the link {@link module:engine/view/attributeelement~AttributeElement} under\n\t * the {@link module:engine/view/document~Document editing view's} selection or `null`\n\t * if there is none.\n\t *\n\t * **Note**: For a non–collapsed selection, the link element is returned when **fully**\n\t * selected and the **only** element within the selection boundaries, or when\n\t * a linked widget is selected.\n\t *\n\t * @private\n\t * @returns {module:engine/view/attributeelement~AttributeElement|null}\n\t */\n\t_getSelectedLinkElement() {\n\t\tconst view = this.editor.editing.view;\n\t\tconst selection = view.document.selection;\n\t\tconst selectedElement = selection.getSelectedElement();\n\n\t\t// The selection is collapsed or some widget is selected (especially inline widget).\n\t\tif ( selection.isCollapsed || selectedElement && isWidget( selectedElement ) ) {\n\t\t\treturn findLinkElementAncestor( selection.getFirstPosition() );\n\t\t} else {\n\t\t\t// The range for fully selected link is usually anchored in adjacent text nodes.\n\t\t\t// Trim it to get closer to the actual link element.\n\t\t\tconst range = selection.getFirstRange().getTrimmed();\n\t\t\tconst startLink = findLinkElementAncestor( range.start );\n\t\t\tconst endLink = findLinkElementAncestor( range.end );\n\n\t\t\tif ( !startLink || startLink != endLink ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Check if the link element is fully selected.\n\t\t\tif ( view.createRangeIn( startLink ).getTrimmed().isEqual( range ) ) {\n\t\t\t\treturn startLink;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Displays a fake visual selection when the contextual balloon is displayed.\n\t *\n\t * This adds a 'link-ui' marker into the document that is rendered as a highlight on selected text fragment.\n\t *\n\t * @private\n\t */\n\t_showFakeVisualSelection() {\n\t\tconst model = this.editor.model;\n\n\t\tmodel.change( writer => {\n\t\t\tconst range = model.document.selection.getFirstRange();\n\n\t\t\tif ( model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ) {\n\t\t\t\twriter.updateMarker( VISUAL_SELECTION_MARKER_NAME, { range } );\n\t\t\t} else {\n\t\t\t\tif ( range.start.isAtEnd ) {\n\t\t\t\t\tconst startPosition = range.start.getLastMatchingPosition(\n\t\t\t\t\t\t( { item } ) => !model.schema.isContent( item ),\n\t\t\t\t\t\t{ boundaries: range }\n\t\t\t\t\t);\n\n\t\t\t\t\twriter.addMarker( VISUAL_SELECTION_MARKER_NAME, {\n\t\t\t\t\t\tusingOperation: false,\n\t\t\t\t\t\taffectsData: false,\n\t\t\t\t\t\trange: writer.createRange( startPosition, range.end )\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\twriter.addMarker( VISUAL_SELECTION_MARKER_NAME, {\n\t\t\t\t\t\tusingOperation: false,\n\t\t\t\t\t\taffectsData: false,\n\t\t\t\t\t\trange\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Hides the fake visual selection created in {@link #_showFakeVisualSelection}.\n\t *\n\t * @private\n\t */\n\t_hideFakeVisualSelection() {\n\t\tconst model = this.editor.model;\n\n\t\tif ( model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ) {\n\t\t\tmodel.change( writer => {\n\t\t\t\twriter.removeMarker( VISUAL_SELECTION_MARKER_NAME );\n\t\t\t} );\n\t\t}\n\t}\n}\n\n// Returns a link element if there's one among the ancestors of the provided `Position`.\n//\n// @private\n// @param {module:engine/view/position~Position} View position to analyze.\n// @returns {module:engine/view/attributeelement~AttributeElement|null} Link element at the position or null.\nfunction findLinkElementAncestor( position ) {\n\treturn position.getAncestors().find( ancestor => isLinkElement( ancestor ) );\n}\n"],"sourceRoot":""}