PageSourceSearch

https://www.smc.edu.tw/src/ckeditor5/plugins/customLink/customLinkImageUI.js

js smc.edu.tw collected 2026-10-04 16:23:14 UTC 3,645 bytes, 101 lines download raw bytes

1
2import { Plugin, ButtonView,  } from 'ckeditor5';
3import CustomLinkUI from './customLinkUI.js';
4import CustomLinkEditing from './customLinkEditing.js'
5
6const LINK_KEYSTROKE = 'Ctrl+K';
7export default class CustomLinkImageUI extends Plugin {
8	/**
9	 * @inheritDoc
10	 */
11	static get requires() {
12		return [ CustomLinkEditing, CustomLinkUI, 'ImageBlockEditing' ];
13	}
14
15	/**
16	 * @inheritDoc
17	 */
18	static get pluginName() {
19		return 'CustomLinkImageUI';
20	}
21
22	/**
23	 * @inheritDoc
24	 */
25	init() {
26		const editor = this.editor;
27		const viewDocument = editor.editing.view.document;
28
29		this.listenTo( viewDocument, 'click', ( evt, data ) => {
30			if ( this._isSelectedLinkedImage( editor.model.document.selection ) ) {
31				// Prevent browser navigation when clicking a linked image.
32				data.preventDefault();
33
34				// Block the `LinkUI` plugin when an image was clicked.
35				// In such a case, we'd like to display the image toolbar.
36				evt.stop();
37			}
38		}, { priority: 'high' } );
39
40		this._createToolbarLinkImageButton();
41	}
42
43	/**
44	 * Creates a `LinkImageUI` button view.
45	 *
46	 * Clicking this button shows a {@link module:link/linkui~LinkUI#_balloon} attached to the selection.
47	 * When an image is already linked, the view shows {@link module:link/linkui~LinkUI#actionsView} or
48	 * {@link module:link/linkui~LinkUI#formView} if it is not.
49	 *
50	 * @private
51	 */
52	_createToolbarLinkImageButton() {
53		const editor = this.editor;
54		const t = editor.t;
55
56		editor.ui.componentFactory.add( 'customLinkImage', locale => {
57			const button = new ButtonView( locale );
58			const plugin = editor.plugins.get( 'CustomLinkUI' );
59			const linkCommand = editor.commands.get( 'customLink' );
60
61			button.set( {
62				isEnabled: true,
63				label: t( 'Link image' ),
64				icon:         '<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20"><script xmlns=""></script><path d="m11.077 15 .991-1.416a.75.75 0 1 1 1.229.86l-1.148 1.64a.748.748 0 0 1-.217.206 5.251 5.251 0 0 1-8.503-5.955.741.741 0 0 1 .12-.274l1.147-1.639a.75.75 0 1 1 1.228.86L4.933 10.7l.006.003a3.75 3.75 0 0 0 6.132 4.294l.006.004zm5.494-5.335a.748.748 0 0 1-.12.274l-1.147 1.639a.75.75 0 1 1-1.228-.86l.86-1.23a3.75 3.75 0 0 0-6.144-4.301l-.86 1.229a.75.75 0 0 1-1.229-.86l1.148-1.64a.748.748 0 0 1 .217-.206 5.251 5.251 0 0 1 8.503 5.955zm-4.563-2.532a.75.75 0 0 1 .184 1.045l-3.155 4.505a.75.75 0 1 1-1.229-.86l3.155-4.506a.75.75 0 0 1 1.045-.184z"></path><script xmlns=""></script><script xmlns=""></script></svg>'				,
65				keystroke: LINK_KEYSTROKE,
66				tooltip: true,
67				isToggleable: true
68			} );
69
70			// Bind button to the command.
71			button.bind( 'isEnabled' ).to( linkCommand, 'isEnabled' );
72			button.bind( 'isOn' ).to( linkCommand, 'value', value => !!value );
73
74			// Show the actionsView or formView (both from LinkUI) on button click depending on whether the image is linked already.
75			this.listenTo( button, 'execute', () => {
76				if ( this._isSelectedLinkedImage( editor.model.document.selection ) ) {
77					plugin._addActionsView();
78				} else {
79					plugin._showUI( true );
80				}
81			} );
82
83			return button;
84		} );
85	}
86
87	/**
88	 * Returns true if a linked image (either block or inline) is the only selected element
89	 * in the model document.
90	 *
91	 * @private
92	 * @param {module:engine/model/selection~Selection} selection
93	 * @returns {Boolean}
94	 */
95	_isSelectedLinkedImage( selection ) {
96		const selectedModelElement = selection.getSelectedElement();
97		const imageUtils = this.editor.plugins.get( 'ImageUtils' );
98
99		return imageUtils.isImage( selectedModelElement ) && selectedModelElement.hasAttribute( 'linkHref' );
100	}
101}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.