UNPKG

4.23 kBJavaScriptView Raw
1/**
2 * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4 */
5/**
6 * @module table/utils/ui/contextualballoon
7 */
8import { Rect } from 'ckeditor5/src/utils';
9import { BalloonPanelView } from 'ckeditor5/src/ui';
10import { getTableWidgetAncestor } from './widget';
11const DEFAULT_BALLOON_POSITIONS = BalloonPanelView.defaultPositions;
12const BALLOON_POSITIONS = [
13 DEFAULT_BALLOON_POSITIONS.northArrowSouth,
14 DEFAULT_BALLOON_POSITIONS.northArrowSouthWest,
15 DEFAULT_BALLOON_POSITIONS.northArrowSouthEast,
16 DEFAULT_BALLOON_POSITIONS.southArrowNorth,
17 DEFAULT_BALLOON_POSITIONS.southArrowNorthWest,
18 DEFAULT_BALLOON_POSITIONS.southArrowNorthEast,
19 DEFAULT_BALLOON_POSITIONS.viewportStickyNorth
20];
21/**
22 * A helper utility that positions the
23 * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} instance
24 * with respect to the table in the editor content, if one is selected.
25 *
26 * @param editor The editor instance.
27 * @param target Either "cell" or "table". Determines the target the balloon will be attached to.
28 */
29export function repositionContextualBalloon(editor, target) {
30 const balloon = editor.plugins.get('ContextualBalloon');
31 if (getTableWidgetAncestor(editor.editing.view.document.selection)) {
32 let position;
33 if (target === 'cell') {
34 position = getBalloonCellPositionData(editor);
35 }
36 else {
37 position = getBalloonTablePositionData(editor);
38 }
39 balloon.updatePosition(position);
40 }
41}
42/**
43 * Returns the positioning options that control the geometry of the
44 * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} with respect
45 * to the selected table in the editor content.
46 *
47 * @param editor The editor instance.
48 */
49export function getBalloonTablePositionData(editor) {
50 const firstPosition = editor.model.document.selection.getFirstPosition();
51 const modelTable = firstPosition.findAncestor('table');
52 const viewTable = editor.editing.mapper.toViewElement(modelTable);
53 return {
54 target: editor.editing.view.domConverter.mapViewToDom(viewTable),
55 positions: BALLOON_POSITIONS
56 };
57}
58/**
59 * Returns the positioning options that control the geometry of the
60 * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} with respect
61 * to the selected table cell in the editor content.
62 *
63 * @param editor The editor instance.
64 */
65export function getBalloonCellPositionData(editor) {
66 const mapper = editor.editing.mapper;
67 const domConverter = editor.editing.view.domConverter;
68 const selection = editor.model.document.selection;
69 if (selection.rangeCount > 1) {
70 return {
71 target: () => createBoundingRect(selection.getRanges(), editor),
72 positions: BALLOON_POSITIONS
73 };
74 }
75 const modelTableCell = getTableCellAtPosition(selection.getFirstPosition());
76 const viewTableCell = mapper.toViewElement(modelTableCell);
77 return {
78 target: domConverter.mapViewToDom(viewTableCell),
79 positions: BALLOON_POSITIONS
80 };
81}
82/**
83 * Returns the first selected table cell from a multi-cell or in-cell selection.
84 *
85 * @param position Document position.
86 */
87function getTableCellAtPosition(position) {
88 const isTableCellSelected = position.nodeAfter && position.nodeAfter.is('element', 'tableCell');
89 return isTableCellSelected ? position.nodeAfter : position.findAncestor('tableCell');
90}
91/**
92 * Returns bounding rectangle for given model ranges.
93 *
94 * @param ranges Model ranges that the bounding rect should be returned for.
95 * @param editor The editor instance.
96 */
97function createBoundingRect(ranges, editor) {
98 const mapper = editor.editing.mapper;
99 const domConverter = editor.editing.view.domConverter;
100 const rects = Array.from(ranges).map(range => {
101 const modelTableCell = getTableCellAtPosition(range.start);
102 const viewTableCell = mapper.toViewElement(modelTableCell);
103 return new Rect(domConverter.mapViewToDom(viewTableCell));
104 });
105 return Rect.getBoundingRect(rects);
106}