@ckeditor/ckeditor5-table 0.0.0-nightly-next-20260127.0 → 0.0.0-nightly-20260128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/table.js +5 -0
- package/build/translations/af.js +1 -0
- package/build/translations/ar.js +1 -0
- package/build/translations/ast.js +1 -0
- package/build/translations/az.js +1 -0
- package/build/translations/be.js +1 -0
- package/build/translations/bg.js +1 -0
- package/build/translations/bn.js +1 -0
- package/build/translations/bs.js +1 -0
- package/build/translations/ca.js +1 -0
- package/build/translations/cs.js +1 -0
- package/build/translations/da.js +1 -0
- package/build/translations/de-ch.js +1 -0
- package/build/translations/de.js +1 -0
- package/build/translations/el.js +1 -0
- package/build/translations/en-au.js +1 -0
- package/build/translations/en-gb.js +1 -0
- package/build/translations/eo.js +1 -0
- package/build/translations/es-co.js +1 -0
- package/build/translations/es.js +1 -0
- package/build/translations/et.js +1 -0
- package/build/translations/eu.js +1 -0
- package/build/translations/fa.js +1 -0
- package/build/translations/fi.js +1 -0
- package/build/translations/fr.js +1 -0
- package/build/translations/gl.js +1 -0
- package/build/translations/gu.js +1 -0
- package/build/translations/he.js +1 -0
- package/build/translations/hi.js +1 -0
- package/build/translations/hr.js +1 -0
- package/build/translations/hu.js +1 -0
- package/build/translations/hy.js +1 -0
- package/build/translations/id.js +1 -0
- package/build/translations/it.js +1 -0
- package/build/translations/ja.js +1 -0
- package/build/translations/jv.js +1 -0
- package/build/translations/kk.js +1 -0
- package/build/translations/km.js +1 -0
- package/build/translations/kn.js +1 -0
- package/build/translations/ko.js +1 -0
- package/build/translations/ku.js +1 -0
- package/build/translations/lt.js +1 -0
- package/build/translations/lv.js +1 -0
- package/build/translations/ms.js +1 -0
- package/build/translations/nb.js +1 -0
- package/build/translations/ne.js +1 -0
- package/build/translations/nl.js +1 -0
- package/build/translations/no.js +1 -0
- package/build/translations/oc.js +1 -0
- package/build/translations/pl.js +1 -0
- package/build/translations/pt-br.js +1 -0
- package/build/translations/pt.js +1 -0
- package/build/translations/ro.js +1 -0
- package/build/translations/ru.js +1 -0
- package/build/translations/si.js +1 -0
- package/build/translations/sk.js +1 -0
- package/build/translations/sl.js +1 -0
- package/build/translations/sq.js +1 -0
- package/build/translations/sr-latn.js +1 -0
- package/build/translations/sr.js +1 -0
- package/build/translations/sv.js +1 -0
- package/build/translations/th.js +1 -0
- package/build/translations/ti.js +1 -0
- package/build/translations/tk.js +1 -0
- package/build/translations/tr.js +1 -0
- package/build/translations/tt.js +1 -0
- package/build/translations/ug.js +1 -0
- package/build/translations/uk.js +1 -0
- package/build/translations/ur.js +1 -0
- package/build/translations/uz.js +1 -0
- package/build/translations/vi.js +1 -0
- package/build/translations/zh-cn.js +1 -0
- package/build/translations/zh.js +1 -0
- package/ckeditor5-metadata.json +7 -16
- package/dist/index-content.css +30 -30
- package/dist/index-editor.css +170 -104
- package/dist/index.css +237 -147
- package/dist/index.css.map +1 -1
- package/dist/index.js +2433 -448
- package/dist/index.js.map +1 -1
- package/lang/contexts.json +82 -0
- package/lang/translations/af.po +332 -0
- package/lang/translations/ar.po +332 -0
- package/lang/translations/ast.po +332 -0
- package/lang/translations/az.po +332 -0
- package/lang/translations/be.po +332 -0
- package/lang/translations/bg.po +332 -0
- package/lang/translations/bn.po +334 -0
- package/lang/translations/bs.po +332 -0
- package/lang/translations/ca.po +332 -0
- package/lang/translations/cs.po +332 -0
- package/lang/translations/da.po +332 -0
- package/lang/translations/de-ch.po +332 -0
- package/lang/translations/de.po +332 -0
- package/lang/translations/el.po +332 -0
- package/lang/translations/en-au.po +332 -0
- package/lang/translations/en-gb.po +332 -0
- package/lang/translations/en.po +332 -0
- package/lang/translations/eo.po +332 -0
- package/lang/translations/es-co.po +332 -0
- package/lang/translations/es.po +332 -0
- package/lang/translations/et.po +332 -0
- package/lang/translations/eu.po +332 -0
- package/lang/translations/fa.po +332 -0
- package/lang/translations/fi.po +332 -0
- package/lang/translations/fr.po +332 -0
- package/lang/translations/gl.po +332 -0
- package/lang/translations/gu.po +332 -0
- package/lang/translations/he.po +332 -0
- package/lang/translations/hi.po +332 -0
- package/lang/translations/hr.po +332 -0
- package/lang/translations/hu.po +332 -0
- package/lang/translations/hy.po +332 -0
- package/lang/translations/id.po +332 -0
- package/lang/translations/it.po +332 -0
- package/lang/translations/ja.po +332 -0
- package/lang/translations/jv.po +332 -0
- package/lang/translations/kk.po +332 -0
- package/lang/translations/km.po +332 -0
- package/lang/translations/kn.po +332 -0
- package/lang/translations/ko.po +332 -0
- package/lang/translations/ku.po +332 -0
- package/lang/translations/lt.po +332 -0
- package/lang/translations/lv.po +332 -0
- package/lang/translations/ms.po +332 -0
- package/lang/translations/nb.po +332 -0
- package/lang/translations/ne.po +332 -0
- package/lang/translations/nl.po +332 -0
- package/lang/translations/no.po +332 -0
- package/lang/translations/oc.po +332 -0
- package/lang/translations/pl.po +332 -0
- package/lang/translations/pt-br.po +332 -0
- package/lang/translations/pt.po +332 -0
- package/lang/translations/ro.po +332 -0
- package/lang/translations/ru.po +332 -0
- package/lang/translations/si.po +332 -0
- package/lang/translations/sk.po +332 -0
- package/lang/translations/sl.po +332 -0
- package/lang/translations/sq.po +332 -0
- package/lang/translations/sr-latn.po +332 -0
- package/lang/translations/sr.po +332 -0
- package/lang/translations/sv.po +332 -0
- package/lang/translations/th.po +332 -0
- package/lang/translations/ti.po +332 -0
- package/lang/translations/tk.po +332 -0
- package/lang/translations/tr.po +332 -0
- package/lang/translations/tt.po +332 -0
- package/lang/translations/ug.po +332 -0
- package/lang/translations/uk.po +332 -0
- package/lang/translations/ur.po +332 -0
- package/lang/translations/uz.po +332 -0
- package/lang/translations/vi.po +332 -0
- package/lang/translations/zh-cn.po +332 -0
- package/lang/translations/zh.po +332 -0
- package/package.json +49 -26
- package/{dist → src}/augmentation.d.ts +15 -0
- package/src/augmentation.js +5 -0
- package/{dist → src}/commands/insertcolumncommand.d.ts +1 -1
- package/src/commands/insertcolumncommand.js +71 -0
- package/{dist → src}/commands/insertrowcommand.d.ts +1 -1
- package/src/commands/insertrowcommand.js +70 -0
- package/{dist → src}/commands/inserttablecommand.d.ts +1 -1
- package/src/commands/inserttablecommand.js +69 -0
- package/{dist → src}/commands/inserttablelayoutcommand.d.ts +1 -1
- package/src/commands/inserttablelayoutcommand.js +65 -0
- package/{dist → src}/commands/mergecellcommand.d.ts +3 -3
- package/src/commands/mergecellcommand.js +206 -0
- package/{dist → src}/commands/mergecellscommand.d.ts +1 -1
- package/src/commands/mergecellscommand.js +94 -0
- package/{dist → src}/commands/removecolumncommand.d.ts +1 -1
- package/src/commands/removecolumncommand.js +109 -0
- package/{dist → src}/commands/removerowcommand.d.ts +1 -1
- package/src/commands/removerowcommand.js +82 -0
- package/{dist → src}/commands/selectcolumncommand.d.ts +1 -1
- package/src/commands/selectcolumncommand.js +60 -0
- package/{dist → src}/commands/selectrowcommand.d.ts +1 -1
- package/src/commands/selectrowcommand.js +56 -0
- package/{dist → src}/commands/setheadercolumncommand.d.ts +1 -1
- package/src/commands/setheadercolumncommand.js +76 -0
- package/{dist → src}/commands/setheaderrowcommand.d.ts +1 -1
- package/src/commands/setheaderrowcommand.js +83 -0
- package/{dist → src}/commands/splitcellcommand.d.ts +1 -1
- package/src/commands/splitcellcommand.js +58 -0
- package/{dist → src}/converters/downcast.d.ts +2 -2
- package/src/converters/downcast.js +298 -0
- package/{dist → src}/converters/table-caption-post-fixer.d.ts +1 -1
- package/src/converters/table-caption-post-fixer.js +55 -0
- package/{dist → src}/converters/table-cell-paragraph-post-fixer.d.ts +1 -1
- package/src/converters/table-cell-paragraph-post-fixer.js +109 -0
- package/{dist → src}/converters/table-cell-refresh-handler.d.ts +1 -1
- package/src/converters/table-cell-refresh-handler.js +47 -0
- package/{dist → src}/converters/table-headings-refresh-handler.d.ts +1 -1
- package/src/converters/table-headings-refresh-handler.js +51 -0
- package/{dist → src}/converters/table-layout-post-fixer.d.ts +1 -1
- package/src/converters/table-layout-post-fixer.js +369 -0
- package/{dist → src}/converters/tableproperties.d.ts +2 -2
- package/src/converters/tableproperties.js +444 -0
- package/{dist → src}/converters/upcasttable.d.ts +1 -1
- package/src/converters/upcasttable.js +385 -0
- package/{dist → src}/index.d.ts +5 -2
- package/src/index.js +98 -0
- package/{dist → src}/plaintableoutput.d.ts +1 -1
- package/src/plaintableoutput.js +49 -0
- package/{dist → src}/table.d.ts +2 -2
- package/src/table.js +50 -0
- package/{dist → src}/tablecaption/tablecaptionediting.d.ts +2 -2
- package/src/tablecaption/tablecaptionediting.js +136 -0
- package/{dist → src}/tablecaption/tablecaptionui.d.ts +1 -1
- package/src/tablecaption/tablecaptionui.js +64 -0
- package/{dist → src}/tablecaption/toggletablecaptioncommand.d.ts +1 -1
- package/src/tablecaption/toggletablecaptioncommand.js +105 -0
- package/{dist → src}/tablecaption/utils.d.ts +1 -1
- package/src/tablecaption/utils.js +61 -0
- package/{dist → src}/tablecaption.d.ts +1 -1
- package/src/tablecaption.js +34 -0
- package/{dist → src}/tablecellproperties/commands/tablecellbackgroundcolorcommand.d.ts +1 -1
- package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +30 -0
- package/{dist → src}/tablecellproperties/commands/tablecellbordercolorcommand.d.ts +2 -2
- package/src/tablecellproperties/commands/tablecellbordercolorcommand.js +44 -0
- package/{dist → src}/tablecellproperties/commands/tablecellborderstylecommand.d.ts +2 -2
- package/src/tablecellproperties/commands/tablecellborderstylecommand.js +44 -0
- package/{dist → src}/tablecellproperties/commands/tablecellborderwidthcommand.d.ts +2 -2
- package/src/tablecellproperties/commands/tablecellborderwidthcommand.js +64 -0
- package/{dist → src}/tablecellproperties/commands/tablecellheightcommand.d.ts +1 -1
- package/src/tablecellproperties/commands/tablecellheightcommand.js +51 -0
- package/{dist → src}/tablecellproperties/commands/tablecellhorizontalalignmentcommand.d.ts +1 -1
- package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +30 -0
- package/{dist → src}/tablecellproperties/commands/tablecellpaddingcommand.d.ts +2 -2
- package/src/tablecellproperties/commands/tablecellpaddingcommand.js +64 -0
- package/{dist → src}/tablecellproperties/commands/tablecellpropertycommand.d.ts +2 -2
- package/src/tablecellproperties/commands/tablecellpropertycommand.js +138 -0
- package/{dist → src}/tablecellproperties/commands/tablecelltypecommand.d.ts +6 -2
- package/src/tablecellproperties/commands/tablecelltypecommand.js +167 -0
- package/{dist → src}/tablecellproperties/commands/tablecellverticalalignmentcommand.d.ts +1 -1
- package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js +38 -0
- package/{dist → src}/tablecellproperties/tablecellpropertiesediting.d.ts +1 -1
- package/src/tablecellproperties/tablecellpropertiesediting.js +412 -0
- package/{dist → src}/tablecellproperties/tablecellpropertiesui.d.ts +2 -2
- package/src/tablecellproperties/tablecellpropertiesui.js +385 -0
- package/src/tablecellproperties/tablecellpropertiesuiexperimental.d.ts +128 -0
- package/src/tablecellproperties/tablecellpropertiesuiexperimental.js +408 -0
- package/src/tablecellproperties/ui/tablecellpropertiesview.d.ts +229 -0
- package/src/tablecellproperties/ui/tablecellpropertiesview.js +612 -0
- package/{dist/tablecellproperties/ui/tablecellpropertiesview.d.ts → src/tablecellproperties/ui/tablecellpropertiesviewexperimental.d.ts} +12 -11
- package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.js +744 -0
- package/{dist → src}/tablecellproperties.d.ts +1 -1
- package/src/tablecellproperties.js +40 -0
- package/{dist → src}/tablecellwidth/commands/tablecellwidthcommand.d.ts +1 -1
- package/src/tablecellwidth/commands/tablecellwidthcommand.js +51 -0
- package/{dist → src}/tablecellwidth/tablecellwidthediting.d.ts +1 -1
- package/src/tablecellwidth/tablecellwidthediting.js +53 -0
- package/{dist → src}/tableclipboard.d.ts +3 -3
- package/src/tableclipboard.js +500 -0
- package/src/tablecolumnresize/constants.js +33 -0
- package/{dist → src}/tablecolumnresize/converters.d.ts +1 -1
- package/src/tablecolumnresize/converters.js +62 -0
- package/{dist → src}/tablecolumnresize/tablecolumnresizeediting.d.ts +2 -2
- package/src/tablecolumnresize/tablecolumnresizeediting.js +734 -0
- package/{dist → src}/tablecolumnresize/tablewidthscommand.d.ts +2 -2
- package/src/tablecolumnresize/tablewidthscommand.js +61 -0
- package/{dist → src}/tablecolumnresize/utils.d.ts +2 -2
- package/src/tablecolumnresize/utils.js +370 -0
- package/{dist → src}/tablecolumnresize.d.ts +1 -1
- package/src/tablecolumnresize.js +36 -0
- package/{dist → src}/tableconfig.d.ts +6 -26
- package/src/tableconfig.js +5 -0
- package/{dist → src}/tableediting.d.ts +3 -3
- package/src/tableediting.js +246 -0
- package/{dist → src}/tablekeyboard.d.ts +3 -3
- package/src/tablekeyboard.js +273 -0
- package/{dist → src}/tablelayout/commands/tabletypecommand.d.ts +1 -1
- package/src/tablelayout/commands/tabletypecommand.js +68 -0
- package/{dist → src}/tablelayout/tablelayoutediting.d.ts +1 -1
- package/src/tablelayout/tablelayoutediting.js +295 -0
- package/{dist → src}/tablelayout/tablelayoutui.d.ts +1 -1
- package/src/tablelayout/tablelayoutui.js +196 -0
- package/{dist → src}/tablelayout.d.ts +1 -1
- package/src/tablelayout.js +37 -0
- package/{dist → src}/tablemouse/mouseeventsobserver.d.ts +1 -1
- package/src/tablemouse/mouseeventsobserver.js +34 -0
- package/{dist → src}/tablemouse.d.ts +1 -1
- package/src/tablemouse.js +178 -0
- package/{dist → src}/tableproperties/commands/tablealignmentcommand.d.ts +1 -1
- package/src/tableproperties/commands/tablealignmentcommand.js +30 -0
- package/{dist → src}/tableproperties/commands/tablebackgroundcolorcommand.d.ts +1 -1
- package/src/tableproperties/commands/tablebackgroundcolorcommand.js +30 -0
- package/{dist → src}/tableproperties/commands/tablebordercolorcommand.d.ts +2 -2
- package/src/tableproperties/commands/tablebordercolorcommand.js +44 -0
- package/{dist → src}/tableproperties/commands/tableborderstylecommand.d.ts +2 -2
- package/src/tableproperties/commands/tableborderstylecommand.js +44 -0
- package/{dist → src}/tableproperties/commands/tableborderwidthcommand.d.ts +2 -2
- package/src/tableproperties/commands/tableborderwidthcommand.js +64 -0
- package/{dist → src}/tableproperties/commands/tableheightcommand.d.ts +1 -1
- package/src/tableproperties/commands/tableheightcommand.js +54 -0
- package/{dist → src}/tableproperties/commands/tablepropertycommand.d.ts +2 -2
- package/src/tableproperties/commands/tablepropertycommand.js +103 -0
- package/{dist → src}/tableproperties/commands/tablewidthcommand.d.ts +1 -1
- package/src/tableproperties/commands/tablewidthcommand.js +54 -0
- package/{dist → src}/tableproperties/tablepropertiesediting.d.ts +1 -1
- package/src/tableproperties/tablepropertiesediting.js +546 -0
- package/{dist → src}/tableproperties/tablepropertiesui.d.ts +2 -2
- package/src/tableproperties/tablepropertiesui.js +374 -0
- package/src/tableproperties/tablepropertiesuiexperimental.d.ts +136 -0
- package/src/tableproperties/tablepropertiesuiexperimental.js +375 -0
- package/{dist → src}/tableproperties/ui/tablepropertiesview.d.ts +2 -10
- package/src/tableproperties/ui/tablepropertiesview.js +520 -0
- package/src/tableproperties/ui/tablepropertiesviewexperimental.d.ts +216 -0
- package/src/tableproperties/ui/tablepropertiesviewexperimental.js +544 -0
- package/{dist → src}/tableproperties.d.ts +1 -1
- package/src/tableproperties.js +40 -0
- package/{dist → src}/tableselection.d.ts +2 -2
- package/src/tableselection.js +323 -0
- package/{dist → src}/tabletoolbar.d.ts +2 -2
- package/src/tabletoolbar.js +63 -0
- package/{dist → src}/tableui.d.ts +1 -1
- package/src/tableui.js +335 -0
- package/{dist → src}/tableutils.d.ts +2 -2
- package/src/tableutils.js +1282 -0
- package/{dist → src}/tablewalker.d.ts +1 -1
- package/src/tablewalker.js +489 -0
- package/{dist → src}/ui/colorinputview.d.ts +2 -2
- package/src/ui/colorinputview.js +305 -0
- package/{dist → src}/ui/inserttableview.d.ts +2 -2
- package/src/ui/inserttableview.js +192 -0
- package/{dist → src}/utils/common.d.ts +2 -2
- package/src/utils/common.js +118 -0
- package/{dist → src}/utils/structure.d.ts +1 -1
- package/src/utils/structure.js +452 -0
- package/{dist → src}/utils/table-properties.d.ts +1 -1
- package/src/utils/table-properties.js +121 -0
- package/{dist → src}/utils/ui/contextualballoon.d.ts +2 -2
- package/src/utils/ui/contextualballoon.js +111 -0
- package/{dist → src}/utils/ui/table-properties.d.ts +2 -2
- package/src/utils/ui/table-properties.js +390 -0
- package/src/utils/ui/table-propertiesexperimental.d.ts +215 -0
- package/src/utils/ui/table-propertiesexperimental.js +391 -0
- package/{dist → src}/utils/ui/widget.d.ts +1 -1
- package/src/utils/ui/widget.js +56 -0
- package/theme/colorinput.css +39 -0
- package/theme/formrow-experimental.css +15 -0
- package/theme/formrow.css +13 -0
- package/theme/inserttable.css +10 -0
- package/theme/table.css +144 -0
- package/theme/tablecaption.css +66 -0
- package/theme/tablecellproperties-experimental.css +4 -0
- package/theme/tablecellproperties.css +28 -0
- package/theme/tablecolumnresize.css +62 -0
- package/theme/tableediting.css +10 -0
- package/theme/tableform-experimental.css +61 -0
- package/theme/tableform.css +64 -0
- package/theme/tablelayout.css +74 -0
- package/theme/tableproperties-experimental.css +78 -0
- package/theme/tableproperties.css +18 -0
- package/theme/tableselection.css +10 -0
- package/dist/tablecellproperties/tablecellpropertiesutils.d.ts +0 -18
- /package/{dist → src}/tablecolumnresize/constants.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command, Plugin } from '@ckeditor/ckeditor5-core/dist/index.js';
|
|
|
6
6
|
import { toWidgetEditable, toWidget, Widget, isWidget, WidgetToolbarRepository } from '@ckeditor/ckeditor5-widget/dist/index.js';
|
|
7
7
|
import { first, global, CKEditorError, KeystrokeHandler, FocusTracker, Collection, getLocalizedArrowKeyCodeDirection, Rect, priorities, DomEmitterMixin, toUnit } from '@ckeditor/ckeditor5-utils/dist/index.js';
|
|
8
8
|
import { isObject, debounce, isEqual, throttle } from 'es-toolkit/compat';
|
|
9
|
-
import { IconTable, IconTableColumn, IconTableRow, IconTableMergeCell,
|
|
9
|
+
import { IconTable, IconTableColumn, IconTableRow, IconTableMergeCell, IconCheck, IconCancel, IconAlignBottom, IconAlignMiddle, IconAlignTop, IconAlignJustify, IconAlignRight, IconAlignCenter, IconAlignLeft, IconTableCellProperties, IconTableLayout, IconTableProperties, IconObjectInlineRight, IconObjectCenter, IconObjectInlineLeft, IconCaption, IconPreviousArrow, IconObjectRight, IconObjectLeft } from '@ckeditor/ckeditor5-icons/dist/index.js';
|
|
10
10
|
import { View, addKeyboardHandlingForGrid, ButtonView, createDropdown, MenuBarMenuView, SwitchButtonView, SplitButtonView, addListToDropdown, UIModel, ViewCollection, FocusCycler, InputTextView, ColorSelectorView, FormHeaderView, FormRowView, submitHandler, LabelView, LabeledFieldView, createLabeledDropdown, createLabeledInputText, ToolbarView, BalloonPanelView, ContextualBalloon, normalizeColorOptions, getLocalizedColorOptions, clickOutsideHandler, DropdownButtonView } from '@ckeditor/ckeditor5-ui/dist/index.js';
|
|
11
11
|
import { ClipboardMarkersUtils, ClipboardPipeline } from '@ckeditor/ckeditor5-clipboard/dist/index.js';
|
|
12
12
|
import { DomEventObserver, isColorStyleValue, isLengthStyleValue, isPercentageStyleValue, addBorderStylesRules, addPaddingStylesRules, addBackgroundStylesRules, addMarginStylesRules, enableViewPlaceholder, ModelElement } from '@ckeditor/ckeditor5-engine/dist/index.js';
|
|
@@ -941,22 +941,6 @@ const downcastTableAlignmentConfig = {
|
|
|
941
941
|
// @if CK_DEBUG // } );
|
|
942
942
|
// @if CK_DEBUG // }
|
|
943
943
|
|
|
944
|
-
/**
|
|
945
|
-
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
946
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
947
|
-
*/ /**
|
|
948
|
-
* @module table/tablecellproperties/tablecellpropertiesutils
|
|
949
|
-
*/ /**
|
|
950
|
-
* Type of the table cell.
|
|
951
|
-
*/ /**
|
|
952
|
-
* Checks if the given cell type represents a header cell.
|
|
953
|
-
*
|
|
954
|
-
* @param cellType The type of the table cell.
|
|
955
|
-
* @returns `true` if the cell type represents a header cell, `false` otherwise.
|
|
956
|
-
*/ function isTableHeaderCellType(cellType) {
|
|
957
|
-
return cellType === 'header' || cellType === 'header-row' || cellType === 'header-column';
|
|
958
|
-
}
|
|
959
|
-
|
|
960
944
|
/**
|
|
961
945
|
* A common method to update the numeric value. If a value is the default one, it will be unset.
|
|
962
946
|
*
|
|
@@ -1058,7 +1042,7 @@ const downcastTableAlignmentConfig = {
|
|
|
1058
1042
|
});
|
|
1059
1043
|
for (const { cell } of tableWalker){
|
|
1060
1044
|
const cellType = cell.getAttribute('tableCellType');
|
|
1061
|
-
if (
|
|
1045
|
+
if (cellType !== 'header') {
|
|
1062
1046
|
return false;
|
|
1063
1047
|
}
|
|
1064
1048
|
}
|
|
@@ -1069,8 +1053,8 @@ const downcastTableAlignmentConfig = {
|
|
|
1069
1053
|
*
|
|
1070
1054
|
* @internal
|
|
1071
1055
|
*/ function isTableCellTypeEnabled(editor) {
|
|
1072
|
-
const { model } = editor;
|
|
1073
|
-
return model.schema.checkAttribute('tableCell', 'tableCellType');
|
|
1056
|
+
const { model, config } = editor;
|
|
1057
|
+
return model.schema.checkAttribute('tableCell', 'tableCellType') && config.get('experimentalFlags.tableCellTypeSupport') === true;
|
|
1074
1058
|
}
|
|
1075
1059
|
|
|
1076
1060
|
/**
|
|
@@ -2085,8 +2069,7 @@ const downcastTableAlignmentConfig = {
|
|
|
2085
2069
|
return (tableCell, { writer })=>{
|
|
2086
2070
|
// If the table cell type feature is enabled, then we can simply check the cell type attribute.
|
|
2087
2071
|
if (options.cellTypeEnabled?.()) {
|
|
2088
|
-
const
|
|
2089
|
-
const cellElementName = isTableHeaderCellType(tableCellType) ? 'th' : 'td';
|
|
2072
|
+
const cellElementName = tableCell.getAttribute('tableCellType') === 'header' ? 'th' : 'td';
|
|
2090
2073
|
return createCellElement(writer, cellElementName);
|
|
2091
2074
|
}
|
|
2092
2075
|
// If the table cell type feature is not enabled, we should iterate through the table structure
|
|
@@ -2192,7 +2175,10 @@ const downcastTableAlignmentConfig = {
|
|
|
2192
2175
|
* Downcasts a plain table (also used in the clipboard pipeline).
|
|
2193
2176
|
*/ function convertPlainTable(editor) {
|
|
2194
2177
|
return (table, conversionApi)=>{
|
|
2195
|
-
|
|
2178
|
+
const hasPlainTableOutput = editor.plugins.has('PlainTableOutput');
|
|
2179
|
+
const isClipboardPipeline = conversionApi.options.isClipboardPipeline;
|
|
2180
|
+
const useExtendedAlignment = editor.config.get('experimentalFlags.useExtendedTableBlockAlignment');
|
|
2181
|
+
if (!hasPlainTableOutput && !(useExtendedAlignment && isClipboardPipeline)) {
|
|
2196
2182
|
return null;
|
|
2197
2183
|
}
|
|
2198
2184
|
return downcastPlainTable(table, conversionApi, editor);
|
|
@@ -2202,7 +2188,10 @@ const downcastTableAlignmentConfig = {
|
|
|
2202
2188
|
* Downcasts a plain table caption (also used in the clipboard pipeline).
|
|
2203
2189
|
*/ function convertPlainTableCaption(editor) {
|
|
2204
2190
|
return (modelElement, { writer, options })=>{
|
|
2205
|
-
|
|
2191
|
+
const hasPlainTableOutput = editor.plugins.has('PlainTableOutput');
|
|
2192
|
+
const isClipboardPipeline = options.isClipboardPipeline;
|
|
2193
|
+
const useExtendedAlignment = editor.config.get('experimentalFlags.useExtendedTableBlockAlignment');
|
|
2194
|
+
if (!hasPlainTableOutput && !(useExtendedAlignment && isClipboardPipeline)) {
|
|
2206
2195
|
return null;
|
|
2207
2196
|
}
|
|
2208
2197
|
if (modelElement.parent.name === 'table') {
|
|
@@ -2290,7 +2279,10 @@ const downcastTableAlignmentConfig = {
|
|
|
2290
2279
|
return dispatcher.on(`attribute:${modelAttribute}:table`, (evt, data, conversionApi)=>{
|
|
2291
2280
|
const { item, attributeNewValue } = data;
|
|
2292
2281
|
const { mapper, writer } = conversionApi;
|
|
2293
|
-
|
|
2282
|
+
const hasPlainTableOutput = editor.plugins.has('PlainTableOutput');
|
|
2283
|
+
const isClipboardPipeline = conversionApi.options.isClipboardPipeline;
|
|
2284
|
+
const useExtendedAlignment = editor.config.get('experimentalFlags.useExtendedTableBlockAlignment');
|
|
2285
|
+
if (!hasPlainTableOutput && !(useExtendedAlignment && isClipboardPipeline)) {
|
|
2294
2286
|
return;
|
|
2295
2287
|
}
|
|
2296
2288
|
if (!conversionApi.consumable.consume(item, evt.name)) {
|
|
@@ -3518,7 +3510,6 @@ const downcastTableAlignmentConfig = {
|
|
|
3518
3510
|
const isCopyStructure = options.copyStructureFromAbove !== undefined;
|
|
3519
3511
|
const copyStructureFrom = options.copyStructureFromAbove ? insertAt - 1 : insertAt;
|
|
3520
3512
|
const cellTypeEnabled = isTableCellTypeEnabled(this.editor);
|
|
3521
|
-
const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
|
|
3522
3513
|
const rows = this.getRows(table);
|
|
3523
3514
|
const columns = this.getColumns(table);
|
|
3524
3515
|
if (insertAt > rows) {
|
|
@@ -3532,6 +3523,7 @@ const downcastTableAlignmentConfig = {
|
|
|
3532
3523
|
}
|
|
3533
3524
|
model.change((writer)=>{
|
|
3534
3525
|
let headingRows = table.getAttribute('headingRows') || 0;
|
|
3526
|
+
const headingColumns = table.getAttribute('headingColumns') || 0;
|
|
3535
3527
|
// Inserting rows inside heading section requires to update `headingRows` attribute as the heading section will grow.
|
|
3536
3528
|
if (headingRows > insertAt) {
|
|
3537
3529
|
headingRows += rowsToInsert;
|
|
@@ -3546,14 +3538,10 @@ const downcastTableAlignmentConfig = {
|
|
|
3546
3538
|
for(let rowOffset = 0; rowOffset < rows.length; rowOffset++){
|
|
3547
3539
|
const row = rows[rowOffset];
|
|
3548
3540
|
for(let columnIndex = 0; columnIndex < columns; columnIndex++){
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
writer,
|
|
3552
|
-
|
|
3553
|
-
row: insertAt + rowOffset,
|
|
3554
|
-
column: columnIndex,
|
|
3555
|
-
scopedHeaders
|
|
3556
|
-
});
|
|
3541
|
+
const cell = row[columnIndex];
|
|
3542
|
+
if (insertAt + rowOffset < headingRows || columnIndex < headingColumns) {
|
|
3543
|
+
writer.setAttribute('tableCellType', 'header', cell);
|
|
3544
|
+
}
|
|
3557
3545
|
}
|
|
3558
3546
|
}
|
|
3559
3547
|
}
|
|
@@ -3588,18 +3576,12 @@ const downcastTableAlignmentConfig = {
|
|
|
3588
3576
|
const insertPosition = writer.createPositionAt(tableRow, 'end');
|
|
3589
3577
|
// Insert the empty cell only if this slot is not row-spanned from any other cell.
|
|
3590
3578
|
if (colspan > 0) {
|
|
3591
|
-
const
|
|
3579
|
+
const insertedCells = createEmptyTableCell(writer, insertPosition, colspan > 1 ? {
|
|
3592
3580
|
colspan
|
|
3593
3581
|
} : undefined);
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
writer,
|
|
3598
|
-
cell: insertedCell,
|
|
3599
|
-
row: insertAt + rowIndex,
|
|
3600
|
-
column: cellIndex,
|
|
3601
|
-
scopedHeaders
|
|
3602
|
-
});
|
|
3582
|
+
// If we insert row in heading section, set proper cell type.
|
|
3583
|
+
if (cellTypeEnabled && (insertAt + rowIndex < headingRows || cellIndex < headingColumns)) {
|
|
3584
|
+
writer.setAttribute('tableCellType', 'header', insertedCells);
|
|
3603
3585
|
}
|
|
3604
3586
|
}
|
|
3605
3587
|
// Skip the col-spanned slots, there won't be any cells.
|
|
@@ -3639,8 +3621,8 @@ const downcastTableAlignmentConfig = {
|
|
|
3639
3621
|
const insertAt = options.at || 0;
|
|
3640
3622
|
const columnsToInsert = options.columns || 1;
|
|
3641
3623
|
const cellTypeEnabled = isTableCellTypeEnabled(this.editor);
|
|
3642
|
-
const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
|
|
3643
3624
|
model.change((writer)=>{
|
|
3625
|
+
const headingRows = table.getAttribute('headingRows') || 0;
|
|
3644
3626
|
let headingColumns = table.getAttribute('headingColumns');
|
|
3645
3627
|
// Inserting columns inside heading section requires to update `headingColumns` attribute as the heading section will grow.
|
|
3646
3628
|
if (insertAt < headingColumns) {
|
|
@@ -3662,14 +3644,9 @@ const downcastTableAlignmentConfig = {
|
|
|
3662
3644
|
if (cellTypeEnabled) {
|
|
3663
3645
|
// If we insert column in heading section, set proper cell type.
|
|
3664
3646
|
for(let columnOffset = 0; columnOffset < insertedCells.length; columnOffset++){
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
cell: insertedCells[columnOffset],
|
|
3669
|
-
row: rowIndex,
|
|
3670
|
-
column: insertAt + columnOffset,
|
|
3671
|
-
scopedHeaders
|
|
3672
|
-
});
|
|
3647
|
+
if (insertAt + columnOffset < headingColumns || rowIndex < headingRows) {
|
|
3648
|
+
writer.setAttribute('tableCellType', 'header', insertedCells[columnOffset]);
|
|
3649
|
+
}
|
|
3673
3650
|
}
|
|
3674
3651
|
}
|
|
3675
3652
|
rowIndex++;
|
|
@@ -3702,14 +3679,9 @@ const downcastTableAlignmentConfig = {
|
|
|
3702
3679
|
// If we insert column in heading section, set proper cell type.
|
|
3703
3680
|
if (cellTypeEnabled) {
|
|
3704
3681
|
for(let columnOffset = 0; columnOffset < insertedCells.length; columnOffset++){
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
cell: insertedCells[columnOffset],
|
|
3709
|
-
row,
|
|
3710
|
-
column: insertAt + columnOffset,
|
|
3711
|
-
scopedHeaders
|
|
3712
|
-
});
|
|
3682
|
+
if (insertAt + columnOffset < headingColumns || row < headingRows) {
|
|
3683
|
+
writer.setAttribute('tableCellType', 'header', insertedCells[columnOffset]);
|
|
3684
|
+
}
|
|
3713
3685
|
}
|
|
3714
3686
|
}
|
|
3715
3687
|
}
|
|
@@ -4220,7 +4192,6 @@ const downcastTableAlignmentConfig = {
|
|
|
4220
4192
|
* Default is `true`.
|
|
4221
4193
|
*/ setHeadingRowsCount(writer, table, headingRows, options = {}) {
|
|
4222
4194
|
const { shallow, resetFormerHeadingCells = true, autoExpand = true } = options;
|
|
4223
|
-
const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
|
|
4224
4195
|
const oldHeadingRows = table.getAttribute('headingRows') || 0;
|
|
4225
4196
|
if (headingRows === oldHeadingRows) {
|
|
4226
4197
|
return;
|
|
@@ -4238,8 +4209,7 @@ const downcastTableAlignmentConfig = {
|
|
|
4238
4209
|
writer,
|
|
4239
4210
|
cell,
|
|
4240
4211
|
row,
|
|
4241
|
-
column
|
|
4242
|
-
scopedHeaders
|
|
4212
|
+
column
|
|
4243
4213
|
});
|
|
4244
4214
|
}
|
|
4245
4215
|
// If heading rows were reduced, set body type to all cells in rows that are no longer in heading section.
|
|
@@ -4261,8 +4231,7 @@ const downcastTableAlignmentConfig = {
|
|
|
4261
4231
|
writer,
|
|
4262
4232
|
cell,
|
|
4263
4233
|
row: cellRow,
|
|
4264
|
-
column
|
|
4265
|
-
scopedHeaders
|
|
4234
|
+
column
|
|
4266
4235
|
});
|
|
4267
4236
|
}
|
|
4268
4237
|
}
|
|
@@ -4295,7 +4264,6 @@ const downcastTableAlignmentConfig = {
|
|
|
4295
4264
|
*/ setHeadingColumnsCount(writer, table, headingColumns, options = {}) {
|
|
4296
4265
|
const { shallow, resetFormerHeadingCells = true, autoExpand = true } = options;
|
|
4297
4266
|
const oldHeadingColumns = table.getAttribute('headingColumns') || 0;
|
|
4298
|
-
const scopedHeaders = !!this.editor.config.get('table.tableCellProperties.scopedHeaders');
|
|
4299
4267
|
if (headingColumns === oldHeadingColumns) {
|
|
4300
4268
|
return;
|
|
4301
4269
|
}
|
|
@@ -4312,8 +4280,7 @@ const downcastTableAlignmentConfig = {
|
|
|
4312
4280
|
writer,
|
|
4313
4281
|
cell,
|
|
4314
4282
|
row,
|
|
4315
|
-
column
|
|
4316
|
-
scopedHeaders
|
|
4283
|
+
column
|
|
4317
4284
|
});
|
|
4318
4285
|
}
|
|
4319
4286
|
// If heading columns were reduced, set body type to all cells in columns that are no longer in heading section.
|
|
@@ -4335,8 +4302,7 @@ const downcastTableAlignmentConfig = {
|
|
|
4335
4302
|
writer,
|
|
4336
4303
|
cell,
|
|
4337
4304
|
row,
|
|
4338
|
-
column: cellColumn
|
|
4339
|
-
scopedHeaders
|
|
4305
|
+
column: cellColumn
|
|
4340
4306
|
});
|
|
4341
4307
|
}
|
|
4342
4308
|
}
|
|
@@ -4703,23 +4669,14 @@ function compareRangeOrder(rangeA, rangeB) {
|
|
|
4703
4669
|
/**
|
|
4704
4670
|
* Updates the `tableCellType` attribute of a table cell based on its position in the table
|
|
4705
4671
|
* and the table's `headingRows` and `headingColumns` attributes.
|
|
4706
|
-
*/ function updateTableCellType({ writer, table, row, column, cell
|
|
4672
|
+
*/ function updateTableCellType({ writer, table, row, column, cell }) {
|
|
4707
4673
|
const headingRows = table.getAttribute('headingRows') || 0;
|
|
4708
4674
|
const headingColumns = table.getAttribute('headingColumns') || 0;
|
|
4709
4675
|
if (row >= headingRows && column >= headingColumns) {
|
|
4710
4676
|
writer.removeAttribute('tableCellType', cell);
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
let headerCellType = 'header';
|
|
4714
|
-
// If scoped headers are enabled, we prefer to set 'row' or 'column' header types depending on the position.
|
|
4715
|
-
if (scopedHeaders) {
|
|
4716
|
-
if (row < headingRows) {
|
|
4717
|
-
headerCellType = 'header-column';
|
|
4718
|
-
} else {
|
|
4719
|
-
headerCellType = 'header-row';
|
|
4720
|
-
}
|
|
4677
|
+
} else {
|
|
4678
|
+
writer.setAttribute('tableCellType', 'header', cell);
|
|
4721
4679
|
}
|
|
4722
|
-
writer.setAttribute('tableCellType', headerCellType, cell);
|
|
4723
4680
|
}
|
|
4724
4681
|
|
|
4725
4682
|
/**
|
|
@@ -7958,7 +7915,7 @@ const isEmpty = (val)=>val === '';
|
|
|
7958
7915
|
*
|
|
7959
7916
|
* @internal
|
|
7960
7917
|
* @param t The "t" function provided by the editor that is used to localize strings.
|
|
7961
|
-
*/ function getBorderStyleLabels(t) {
|
|
7918
|
+
*/ function getBorderStyleLabels$1(t) {
|
|
7962
7919
|
return {
|
|
7963
7920
|
none: t('None'),
|
|
7964
7921
|
solid: t('Solid'),
|
|
@@ -8028,9 +7985,9 @@ const isEmpty = (val)=>val === '';
|
|
|
8028
7985
|
*
|
|
8029
7986
|
* @internal
|
|
8030
7987
|
* @param defaultStyle The default border.
|
|
8031
|
-
*/ function getBorderStyleDefinitions(view, defaultStyle) {
|
|
7988
|
+
*/ function getBorderStyleDefinitions$1(view, defaultStyle) {
|
|
8032
7989
|
const itemDefinitions = new Collection();
|
|
8033
|
-
const styleLabels = getBorderStyleLabels(view.t);
|
|
7990
|
+
const styleLabels = getBorderStyleLabels$1(view.t);
|
|
8034
7991
|
for(const style in styleLabels){
|
|
8035
7992
|
const definition = {
|
|
8036
7993
|
type: 'button',
|
|
@@ -8073,7 +8030,7 @@ const isEmpty = (val)=>val === '';
|
|
|
8073
8030
|
* @param options.propertyName The name of the observable property in the view.
|
|
8074
8031
|
* @param options.nameToValue A function that maps a button name to a value. By default names are the same as values.
|
|
8075
8032
|
* @param options.defaultValue Default value for the property.
|
|
8076
|
-
*/ function fillToolbar(options) {
|
|
8033
|
+
*/ function fillToolbar$1(options) {
|
|
8077
8034
|
const { view, icons, toolbar, labels, propertyName, nameToValue, defaultValue } = options;
|
|
8078
8035
|
for(const name in labels){
|
|
8079
8036
|
const button = new ButtonView(view.locale);
|
|
@@ -8277,10 +8234,10 @@ const isEmpty = (val)=>val === '';
|
|
|
8277
8234
|
* @param options.defaultColorValue If specified, the color input view will replace the "Remove color" button with
|
|
8278
8235
|
* the "Restore default" button. Instead of clearing the input field, the default color value will be set.
|
|
8279
8236
|
* @param options.colorPickerConfig The configuration of the color picker. You could disable it or define your output format.
|
|
8280
|
-
*/ function getLabeledColorInputCreator(options) {
|
|
8237
|
+
*/ function getLabeledColorInputCreator$1(options) {
|
|
8281
8238
|
return (labeledFieldView, viewUid, statusUid)=>{
|
|
8282
8239
|
const colorInputView = new ColorInputView(labeledFieldView.locale, {
|
|
8283
|
-
colorDefinitions: colorConfigToColorGridDefinitions(options.colorConfig),
|
|
8240
|
+
colorDefinitions: colorConfigToColorGridDefinitions$1(options.colorConfig),
|
|
8284
8241
|
columns: options.columns,
|
|
8285
8242
|
defaultColorValue: options.defaultColorValue,
|
|
8286
8243
|
colorPickerConfig: options.colorPickerConfig
|
|
@@ -8307,7 +8264,7 @@ const isEmpty = (val)=>val === '';
|
|
|
8307
8264
|
const parsedValue = parseFloat(value);
|
|
8308
8265
|
return !Number.isNaN(parsedValue) && value === String(parsedValue);
|
|
8309
8266
|
}
|
|
8310
|
-
function colorConfigToColorGridDefinitions(colorConfig) {
|
|
8267
|
+
function colorConfigToColorGridDefinitions$1(colorConfig) {
|
|
8311
8268
|
return colorConfig.map((item)=>({
|
|
8312
8269
|
color: item.model,
|
|
8313
8270
|
label: item.label,
|
|
@@ -8345,9 +8302,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8345
8302
|
/**
|
|
8346
8303
|
* An input that allows specifying the table cell background color.
|
|
8347
8304
|
*/ backgroundInput;
|
|
8348
|
-
/**
|
|
8349
|
-
* A dropdown that allows selecting the type of the table cell (data or header).
|
|
8350
|
-
*/ cellTypeDropdown;
|
|
8351
8305
|
/**
|
|
8352
8306
|
* An input that allows specifying the table cell padding.
|
|
8353
8307
|
*/ paddingInput;
|
|
@@ -8369,9 +8323,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8369
8323
|
/**
|
|
8370
8324
|
* The "Cancel" button view.
|
|
8371
8325
|
*/ cancelButtonView;
|
|
8372
|
-
/**
|
|
8373
|
-
* The "Back" button view.
|
|
8374
|
-
*/ backButtonView;
|
|
8375
8326
|
/**
|
|
8376
8327
|
* A collection of views that can be focused in the form.
|
|
8377
8328
|
*/ _focusables;
|
|
@@ -8397,13 +8348,11 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8397
8348
|
width: '',
|
|
8398
8349
|
height: '',
|
|
8399
8350
|
horizontalAlignment: '',
|
|
8400
|
-
verticalAlignment: ''
|
|
8401
|
-
cellType: ''
|
|
8351
|
+
verticalAlignment: ''
|
|
8402
8352
|
});
|
|
8403
8353
|
this.options = options;
|
|
8404
8354
|
const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
|
|
8405
8355
|
const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
|
|
8406
|
-
const { cellTypeRowLabel, cellTypeDropdown } = this._createCellTypeField();
|
|
8407
8356
|
const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
|
|
8408
8357
|
const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
|
|
8409
8358
|
this.focusTracker = new FocusTracker();
|
|
@@ -8413,7 +8362,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8413
8362
|
this.borderWidthInput = borderWidthInput;
|
|
8414
8363
|
this.borderColorInput = borderColorInput;
|
|
8415
8364
|
this.backgroundInput = backgroundInput;
|
|
8416
|
-
this.cellTypeDropdown = cellTypeDropdown;
|
|
8417
8365
|
this.paddingInput = this._createPaddingField();
|
|
8418
8366
|
this.widthInput = widthInput;
|
|
8419
8367
|
this.heightInput = heightInput;
|
|
@@ -8425,7 +8373,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8425
8373
|
const { saveButtonView, cancelButtonView } = this._createActionButtons();
|
|
8426
8374
|
this.saveButtonView = saveButtonView;
|
|
8427
8375
|
this.cancelButtonView = cancelButtonView;
|
|
8428
|
-
this.backButtonView = this._createBackButton();
|
|
8429
8376
|
this._focusables = new ViewCollection();
|
|
8430
8377
|
this._focusCycler = new FocusCycler({
|
|
8431
8378
|
focusables: this._focusables,
|
|
@@ -8439,42 +8386,28 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8439
8386
|
}
|
|
8440
8387
|
});
|
|
8441
8388
|
// Form header.
|
|
8442
|
-
|
|
8389
|
+
this.children.add(new FormHeaderView(locale, {
|
|
8443
8390
|
label: this.t('Cell properties')
|
|
8444
|
-
});
|
|
8445
|
-
header.children.add(this.backButtonView, 0);
|
|
8446
|
-
this.children.add(header);
|
|
8391
|
+
}));
|
|
8447
8392
|
// Border row.
|
|
8448
8393
|
this.children.add(new FormRowView(locale, {
|
|
8449
8394
|
labelView: borderRowLabel,
|
|
8450
8395
|
children: [
|
|
8451
8396
|
borderRowLabel,
|
|
8452
8397
|
borderStyleDropdown,
|
|
8453
|
-
|
|
8454
|
-
|
|
8398
|
+
borderColorInput,
|
|
8399
|
+
borderWidthInput
|
|
8455
8400
|
],
|
|
8456
8401
|
class: 'ck-table-form__border-row'
|
|
8457
8402
|
}));
|
|
8458
|
-
// Background
|
|
8403
|
+
// Background.
|
|
8459
8404
|
this.children.add(new FormRowView(locale, {
|
|
8405
|
+
labelView: backgroundRowLabel,
|
|
8460
8406
|
children: [
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
cellTypeDropdown
|
|
8466
|
-
],
|
|
8467
|
-
class: 'ck-table-form__cell-type-row'
|
|
8468
|
-
}),
|
|
8469
|
-
new FormRowView(locale, {
|
|
8470
|
-
labelView: backgroundRowLabel,
|
|
8471
|
-
children: [
|
|
8472
|
-
backgroundRowLabel,
|
|
8473
|
-
backgroundInput
|
|
8474
|
-
],
|
|
8475
|
-
class: 'ck-table-form__background-row'
|
|
8476
|
-
})
|
|
8477
|
-
]
|
|
8407
|
+
backgroundRowLabel,
|
|
8408
|
+
backgroundInput
|
|
8409
|
+
],
|
|
8410
|
+
class: 'ck-table-form__background-row'
|
|
8478
8411
|
}));
|
|
8479
8412
|
// Dimensions row and padding.
|
|
8480
8413
|
this.children.add(new FormRowView(locale, {
|
|
@@ -8512,8 +8445,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8512
8445
|
// Action row.
|
|
8513
8446
|
this.children.add(new FormRowView(locale, {
|
|
8514
8447
|
children: [
|
|
8515
|
-
this.
|
|
8516
|
-
this.
|
|
8448
|
+
this.saveButtonView,
|
|
8449
|
+
this.cancelButtonView
|
|
8517
8450
|
],
|
|
8518
8451
|
class: 'ck-table-form__action-row'
|
|
8519
8452
|
}));
|
|
@@ -8552,16 +8485,14 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8552
8485
|
this.borderStyleDropdown,
|
|
8553
8486
|
this.borderColorInput,
|
|
8554
8487
|
this.borderWidthInput,
|
|
8555
|
-
this.cellTypeDropdown,
|
|
8556
8488
|
this.backgroundInput,
|
|
8557
8489
|
this.widthInput,
|
|
8558
8490
|
this.heightInput,
|
|
8559
8491
|
this.paddingInput,
|
|
8560
8492
|
this.horizontalAlignmentToolbar,
|
|
8561
8493
|
this.verticalAlignmentToolbar,
|
|
8562
|
-
this.cancelButtonView,
|
|
8563
8494
|
this.saveButtonView,
|
|
8564
|
-
this.
|
|
8495
|
+
this.cancelButtonView
|
|
8565
8496
|
].forEach((view)=>{
|
|
8566
8497
|
// Register the view as focusable.
|
|
8567
8498
|
this._focusables.add(view);
|
|
@@ -8596,7 +8527,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8596
8527
|
width: defaultTableCellProperties.borderWidth,
|
|
8597
8528
|
color: defaultTableCellProperties.borderColor
|
|
8598
8529
|
};
|
|
8599
|
-
const colorInputCreator = getLabeledColorInputCreator({
|
|
8530
|
+
const colorInputCreator = getLabeledColorInputCreator$1({
|
|
8600
8531
|
colorConfig: this.options.borderColors,
|
|
8601
8532
|
columns: 5,
|
|
8602
8533
|
defaultColorValue: defaultBorder.color,
|
|
@@ -8609,7 +8540,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8609
8540
|
const borderRowLabel = new LabelView(locale);
|
|
8610
8541
|
borderRowLabel.text = t('Border');
|
|
8611
8542
|
// -- Style ---------------------------------------------------
|
|
8612
|
-
const styleLabels = getBorderStyleLabels(t);
|
|
8543
|
+
const styleLabels = getBorderStyleLabels$1(t);
|
|
8613
8544
|
const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
|
|
8614
8545
|
borderStyleDropdown.set({
|
|
8615
8546
|
label: accessibleLabel,
|
|
@@ -8629,7 +8560,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8629
8560
|
this.borderStyle = evt.source._borderStyleValue;
|
|
8630
8561
|
});
|
|
8631
8562
|
borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
|
|
8632
|
-
addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
|
|
8563
|
+
addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions$1(this, defaultBorder.style), {
|
|
8633
8564
|
role: 'menu',
|
|
8634
8565
|
ariaLabel: accessibleLabel
|
|
8635
8566
|
});
|
|
@@ -8640,7 +8571,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8640
8571
|
class: 'ck-table-form__border-width'
|
|
8641
8572
|
});
|
|
8642
8573
|
borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
|
|
8643
|
-
borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$
|
|
8574
|
+
borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$3);
|
|
8644
8575
|
borderWidthInput.fieldView.on('input', ()=>{
|
|
8645
8576
|
this.borderWidth = borderWidthInput.fieldView.element.value;
|
|
8646
8577
|
});
|
|
@@ -8651,7 +8582,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8651
8582
|
class: 'ck-table-form__border-color'
|
|
8652
8583
|
});
|
|
8653
8584
|
borderColorInput.fieldView.bind('value').to(this, 'borderColor');
|
|
8654
|
-
borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$
|
|
8585
|
+
borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$3);
|
|
8655
8586
|
borderColorInput.fieldView.on('input', ()=>{
|
|
8656
8587
|
this.borderColor = borderColorInput.fieldView.value;
|
|
8657
8588
|
});
|
|
@@ -8659,12 +8590,12 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8659
8590
|
this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
|
|
8660
8591
|
// When removing the border (`border-style:none`), clear the remaining `border-*` properties.
|
|
8661
8592
|
// See: https://github.com/ckeditor/ckeditor5/issues/6227.
|
|
8662
|
-
if (!isBorderStyleSet$
|
|
8593
|
+
if (!isBorderStyleSet$3(newValue)) {
|
|
8663
8594
|
this.borderColor = '';
|
|
8664
8595
|
this.borderWidth = '';
|
|
8665
8596
|
}
|
|
8666
8597
|
// When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
|
|
8667
|
-
if (!isBorderStyleSet$
|
|
8598
|
+
if (!isBorderStyleSet$3(oldValue)) {
|
|
8668
8599
|
this.borderColor = defaultBorder.color;
|
|
8669
8600
|
this.borderWidth = defaultBorder.width;
|
|
8670
8601
|
}
|
|
@@ -8687,7 +8618,7 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8687
8618
|
const backgroundRowLabel = new LabelView(locale);
|
|
8688
8619
|
backgroundRowLabel.text = t('Background');
|
|
8689
8620
|
// -- Background color input -----------------------------------
|
|
8690
|
-
const colorInputCreator = getLabeledColorInputCreator({
|
|
8621
|
+
const colorInputCreator = getLabeledColorInputCreator$1({
|
|
8691
8622
|
colorConfig: this.options.backgroundColors,
|
|
8692
8623
|
columns: 5,
|
|
8693
8624
|
defaultColorValue: this.options.defaultTableCellProperties.backgroundColor,
|
|
@@ -8707,46 +8638,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8707
8638
|
backgroundInput
|
|
8708
8639
|
};
|
|
8709
8640
|
}
|
|
8710
|
-
/**
|
|
8711
|
-
* Create cell type field.
|
|
8712
|
-
*
|
|
8713
|
-
* * {@link #cellTypeDropdown}.
|
|
8714
|
-
*
|
|
8715
|
-
* @internal
|
|
8716
|
-
*/ _createCellTypeField() {
|
|
8717
|
-
const locale = this.locale;
|
|
8718
|
-
const t = this.t;
|
|
8719
|
-
const cellTypeRowLabel = new LabelView(locale);
|
|
8720
|
-
cellTypeRowLabel.text = t('Cell type');
|
|
8721
|
-
const cellTypeLabels = this._cellTypeLabels;
|
|
8722
|
-
const cellTypeDropdown = new LabeledFieldView(locale, createLabeledDropdown);
|
|
8723
|
-
cellTypeDropdown.set({
|
|
8724
|
-
label: t('Cell type'),
|
|
8725
|
-
class: 'ck-table-cell-properties-form__cell-type'
|
|
8726
|
-
});
|
|
8727
|
-
cellTypeDropdown.fieldView.buttonView.set({
|
|
8728
|
-
ariaLabel: t('Cell type'),
|
|
8729
|
-
ariaLabelledBy: undefined,
|
|
8730
|
-
isOn: false,
|
|
8731
|
-
withText: true,
|
|
8732
|
-
tooltip: t('Cell type')
|
|
8733
|
-
});
|
|
8734
|
-
cellTypeDropdown.fieldView.buttonView.bind('label').to(this, 'cellType', (value)=>{
|
|
8735
|
-
return cellTypeLabels[value || 'data'];
|
|
8736
|
-
});
|
|
8737
|
-
cellTypeDropdown.fieldView.on('execute', (evt)=>{
|
|
8738
|
-
this.cellType = evt.source._cellTypeValue;
|
|
8739
|
-
});
|
|
8740
|
-
cellTypeDropdown.bind('isEmpty').to(this, 'cellType', (value)=>!value);
|
|
8741
|
-
addListToDropdown(cellTypeDropdown.fieldView, this._getCellTypeDefinitions(), {
|
|
8742
|
-
role: 'menu',
|
|
8743
|
-
ariaLabel: t('Cell type')
|
|
8744
|
-
});
|
|
8745
|
-
return {
|
|
8746
|
-
cellTypeRowLabel,
|
|
8747
|
-
cellTypeDropdown
|
|
8748
|
-
};
|
|
8749
|
-
}
|
|
8750
8641
|
/**
|
|
8751
8642
|
* Creates the following form fields:
|
|
8752
8643
|
*
|
|
@@ -8843,10 +8734,9 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8843
8734
|
horizontalAlignmentToolbar.set({
|
|
8844
8735
|
isCompact: true,
|
|
8845
8736
|
role: 'radiogroup',
|
|
8846
|
-
ariaLabel: t('Horizontal text alignment toolbar')
|
|
8847
|
-
class: 'ck-table-cell-properties-form__horizontal-alignment-toolbar'
|
|
8737
|
+
ariaLabel: t('Horizontal text alignment toolbar')
|
|
8848
8738
|
});
|
|
8849
|
-
fillToolbar({
|
|
8739
|
+
fillToolbar$1({
|
|
8850
8740
|
view: this,
|
|
8851
8741
|
icons: ALIGNMENT_ICONS,
|
|
8852
8742
|
toolbar: horizontalAlignmentToolbar,
|
|
@@ -8870,10 +8760,9 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8870
8760
|
verticalAlignmentToolbar.set({
|
|
8871
8761
|
isCompact: true,
|
|
8872
8762
|
role: 'radiogroup',
|
|
8873
|
-
ariaLabel: t('Vertical text alignment toolbar')
|
|
8874
|
-
class: 'ck-table-cell-properties-form__vertical-alignment-toolbar'
|
|
8763
|
+
ariaLabel: t('Vertical text alignment toolbar')
|
|
8875
8764
|
});
|
|
8876
|
-
fillToolbar({
|
|
8765
|
+
fillToolbar$1({
|
|
8877
8766
|
view: this,
|
|
8878
8767
|
icons: ALIGNMENT_ICONS,
|
|
8879
8768
|
toolbar: verticalAlignmentToolbar,
|
|
@@ -8905,7 +8794,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8905
8794
|
];
|
|
8906
8795
|
saveButtonView.set({
|
|
8907
8796
|
label: t('Save'),
|
|
8908
|
-
|
|
8797
|
+
icon: IconCheck,
|
|
8798
|
+
class: 'ck-button-save',
|
|
8909
8799
|
type: 'submit',
|
|
8910
8800
|
withText: true
|
|
8911
8801
|
});
|
|
@@ -8914,6 +8804,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8914
8804
|
});
|
|
8915
8805
|
cancelButtonView.set({
|
|
8916
8806
|
label: t('Cancel'),
|
|
8807
|
+
icon: IconCancel,
|
|
8808
|
+
class: 'ck-button-cancel',
|
|
8917
8809
|
withText: true
|
|
8918
8810
|
});
|
|
8919
8811
|
cancelButtonView.delegate('execute').to(this, 'cancel');
|
|
@@ -8922,47 +8814,6 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8922
8814
|
cancelButtonView
|
|
8923
8815
|
};
|
|
8924
8816
|
}
|
|
8925
|
-
/**
|
|
8926
|
-
* Creates a back button view that cancels the form.
|
|
8927
|
-
*/ _createBackButton() {
|
|
8928
|
-
const t = this.locale.t;
|
|
8929
|
-
const backButton = new ButtonView(this.locale);
|
|
8930
|
-
backButton.set({
|
|
8931
|
-
class: 'ck-button-back',
|
|
8932
|
-
label: t('Back'),
|
|
8933
|
-
icon: IconPreviousArrow,
|
|
8934
|
-
tooltip: true
|
|
8935
|
-
});
|
|
8936
|
-
backButton.delegate('execute').to(this, 'cancel');
|
|
8937
|
-
return backButton;
|
|
8938
|
-
}
|
|
8939
|
-
/**
|
|
8940
|
-
* Creates the cell type dropdown definitions.
|
|
8941
|
-
*/ _getCellTypeDefinitions() {
|
|
8942
|
-
const itemDefinitions = new Collection();
|
|
8943
|
-
const labels = this._cellTypeLabels;
|
|
8944
|
-
const types = [
|
|
8945
|
-
'data',
|
|
8946
|
-
'header'
|
|
8947
|
-
];
|
|
8948
|
-
if (this.options.showScopedHeaderOptions) {
|
|
8949
|
-
types.push('header-column', 'header-row');
|
|
8950
|
-
}
|
|
8951
|
-
for (const type of types){
|
|
8952
|
-
const definition = {
|
|
8953
|
-
type: 'button',
|
|
8954
|
-
model: new UIModel({
|
|
8955
|
-
_cellTypeValue: type,
|
|
8956
|
-
label: labels[type],
|
|
8957
|
-
role: 'menuitemradio',
|
|
8958
|
-
withText: true
|
|
8959
|
-
})
|
|
8960
|
-
};
|
|
8961
|
-
definition.model.bind('isOn').to(this, 'cellType', (value)=>value === type);
|
|
8962
|
-
itemDefinitions.add(definition);
|
|
8963
|
-
}
|
|
8964
|
-
return itemDefinitions;
|
|
8965
|
-
}
|
|
8966
8817
|
/**
|
|
8967
8818
|
* Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
|
|
8968
8819
|
*/ get _horizontalAlignmentLabels() {
|
|
@@ -8999,19 +8850,8 @@ function colorConfigToColorGridDefinitions(colorConfig) {
|
|
|
8999
8850
|
bottom: t('Align cell text to the bottom')
|
|
9000
8851
|
};
|
|
9001
8852
|
}
|
|
9002
|
-
/**
|
|
9003
|
-
* Provides localized labels for {@link #cellTypeDropdown}.
|
|
9004
|
-
*/ get _cellTypeLabels() {
|
|
9005
|
-
const t = this.t;
|
|
9006
|
-
return {
|
|
9007
|
-
data: t('Data cell'),
|
|
9008
|
-
header: t('Header cell'),
|
|
9009
|
-
'header-column': t('Column header'),
|
|
9010
|
-
'header-row': t('Row header')
|
|
9011
|
-
};
|
|
9012
|
-
}
|
|
9013
8853
|
}
|
|
9014
|
-
function isBorderStyleSet$
|
|
8854
|
+
function isBorderStyleSet$3(value) {
|
|
9015
8855
|
return value !== 'none';
|
|
9016
8856
|
}
|
|
9017
8857
|
|
|
@@ -9110,9 +8950,9 @@ const BALLOON_POSITIONS = /* #__PURE__ */ (()=>[
|
|
|
9110
8950
|
return Rect.getBoundingRect(rects);
|
|
9111
8951
|
}
|
|
9112
8952
|
|
|
9113
|
-
const ERROR_TEXT_TIMEOUT$
|
|
8953
|
+
const ERROR_TEXT_TIMEOUT$3 = 500;
|
|
9114
8954
|
// Map of view properties and related commands.
|
|
9115
|
-
const propertyToCommandMap$
|
|
8955
|
+
const propertyToCommandMap$3 = {
|
|
9116
8956
|
borderStyle: 'tableCellBorderStyle',
|
|
9117
8957
|
borderColor: 'tableCellBorderColor',
|
|
9118
8958
|
borderWidth: 'tableCellBorderWidth',
|
|
@@ -9121,8 +8961,7 @@ const propertyToCommandMap$1 = {
|
|
|
9121
8961
|
padding: 'tableCellPadding',
|
|
9122
8962
|
backgroundColor: 'tableCellBackgroundColor',
|
|
9123
8963
|
horizontalAlignment: 'tableCellHorizontalAlignment',
|
|
9124
|
-
verticalAlignment: 'tableCellVerticalAlignment'
|
|
9125
|
-
cellType: 'tableCellType'
|
|
8964
|
+
verticalAlignment: 'tableCellVerticalAlignment'
|
|
9126
8965
|
};
|
|
9127
8966
|
/**
|
|
9128
8967
|
* The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
|
|
@@ -9209,7 +9048,7 @@ const propertyToCommandMap$1 = {
|
|
|
9209
9048
|
tooltip: true
|
|
9210
9049
|
});
|
|
9211
9050
|
this.listenTo(view, 'execute', ()=>this._showView());
|
|
9212
|
-
const commands = Object.values(propertyToCommandMap$
|
|
9051
|
+
const commands = Object.values(propertyToCommandMap$3).map((commandName)=>editor.commands.get(commandName));
|
|
9213
9052
|
view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
|
|
9214
9053
|
return view;
|
|
9215
9054
|
});
|
|
@@ -9231,7 +9070,6 @@ const propertyToCommandMap$1 = {
|
|
|
9231
9070
|
*/ _createPropertiesView(defaultTableCellProperties) {
|
|
9232
9071
|
const editor = this.editor;
|
|
9233
9072
|
const config = editor.config.get('table.tableCellProperties');
|
|
9234
|
-
const scopedHeaders = !!editor.config.get('table.tableCellProperties.scopedHeaders');
|
|
9235
9073
|
const borderColorsConfig = normalizeColorOptions(config.borderColors);
|
|
9236
9074
|
const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
|
|
9237
9075
|
const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
|
|
@@ -9241,8 +9079,7 @@ const propertyToCommandMap$1 = {
|
|
|
9241
9079
|
borderColors: localizedBorderColors,
|
|
9242
9080
|
backgroundColors: localizedBackgroundColors,
|
|
9243
9081
|
defaultTableCellProperties,
|
|
9244
|
-
colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false
|
|
9245
|
-
showScopedHeaderOptions: scopedHeaders
|
|
9082
|
+
colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false
|
|
9246
9083
|
});
|
|
9247
9084
|
const t = editor.t;
|
|
9248
9085
|
// Render the view so its #element is available for the clickOutsideHandler.
|
|
@@ -9317,11 +9154,6 @@ const propertyToCommandMap$1 = {
|
|
|
9317
9154
|
}));
|
|
9318
9155
|
view.on('change:horizontalAlignment', this._getPropertyChangeCallback('tableCellHorizontalAlignment'));
|
|
9319
9156
|
view.on('change:verticalAlignment', this._getPropertyChangeCallback('tableCellVerticalAlignment'));
|
|
9320
|
-
const cellTypeCommand = editor.commands.get('tableCellType');
|
|
9321
|
-
if (cellTypeCommand) {
|
|
9322
|
-
view.cellTypeDropdown.bind('isEnabled').to(cellTypeCommand, 'isEnabled');
|
|
9323
|
-
view.on('change:cellType', this._getPropertyChangeCallback('tableCellType'));
|
|
9324
|
-
}
|
|
9325
9157
|
return view;
|
|
9326
9158
|
}
|
|
9327
9159
|
/**
|
|
@@ -9334,24 +9166,12 @@ const propertyToCommandMap$1 = {
|
|
|
9334
9166
|
*/ _fillViewFormFromCommandValues() {
|
|
9335
9167
|
const commands = this.editor.commands;
|
|
9336
9168
|
const borderStyleCommand = commands.get('tableCellBorderStyle');
|
|
9337
|
-
Object.entries(propertyToCommandMap$
|
|
9338
|
-
const command = commands.get(commandName);
|
|
9339
|
-
if (!command) {
|
|
9340
|
-
return [];
|
|
9341
|
-
}
|
|
9169
|
+
Object.entries(propertyToCommandMap$3).map(([property, commandName])=>{
|
|
9342
9170
|
const propertyKey = property;
|
|
9343
|
-
|
|
9344
|
-
if (propertyKey === 'cellType') {
|
|
9345
|
-
defaultValue = '';
|
|
9346
|
-
} else {
|
|
9347
|
-
defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
|
|
9348
|
-
}
|
|
9349
|
-
const entry = [
|
|
9350
|
-
property,
|
|
9351
|
-
command.value || defaultValue
|
|
9352
|
-
];
|
|
9171
|
+
const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
|
|
9353
9172
|
return [
|
|
9354
|
-
|
|
9173
|
+
property,
|
|
9174
|
+
commands.get(commandName).value || defaultValue
|
|
9355
9175
|
];
|
|
9356
9176
|
}).forEach(([property, value])=>{
|
|
9357
9177
|
// Do not set the `border-color` and `border-width` fields if `border-style:none`.
|
|
@@ -9452,7 +9272,7 @@ const propertyToCommandMap$1 = {
|
|
|
9452
9272
|
const { commandName, viewField, validator, errorText } = options;
|
|
9453
9273
|
const setErrorTextDebounced = debounce(()=>{
|
|
9454
9274
|
viewField.errorText = errorText;
|
|
9455
|
-
}, ERROR_TEXT_TIMEOUT$
|
|
9275
|
+
}, ERROR_TEXT_TIMEOUT$3);
|
|
9456
9276
|
return (evt, propertyName, newValue)=>{
|
|
9457
9277
|
setErrorTextDebounced.cancel();
|
|
9458
9278
|
// Do not execute the command on initial call (opening the table properties view).
|
|
@@ -10112,7 +9932,7 @@ const propertyToCommandMap$1 = {
|
|
|
10112
9932
|
// Check each cell in the current row/column.
|
|
10113
9933
|
for (const { cell, row, column } of walker){
|
|
10114
9934
|
// If we find a non-header cell, this row/column can't be part of the heading section.
|
|
10115
|
-
if (
|
|
9935
|
+
if (cell.getAttribute('tableCellType') !== 'header') {
|
|
10116
9936
|
allCellsAreHeaders = false;
|
|
10117
9937
|
break;
|
|
10118
9938
|
}
|
|
@@ -10238,8 +10058,10 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
|
|
|
10238
10058
|
editor.commands.add('tableCellHorizontalAlignment', new TableCellHorizontalAlignmentCommand(editor, defaultTableCellProperties.horizontalAlignment));
|
|
10239
10059
|
enableVerticalAlignmentProperty(schema, conversion, defaultTableCellProperties.verticalAlignment);
|
|
10240
10060
|
editor.commands.add('tableCellVerticalAlignment', new TableCellVerticalAlignmentCommand(editor, defaultTableCellProperties.verticalAlignment));
|
|
10241
|
-
|
|
10242
|
-
|
|
10061
|
+
if (editor.config.get('experimentalFlags.tableCellTypeSupport')) {
|
|
10062
|
+
enableCellTypeProperty(editor);
|
|
10063
|
+
editor.commands.add('tableCellType', new TableCellTypeCommand(editor));
|
|
10064
|
+
}
|
|
10243
10065
|
}
|
|
10244
10066
|
}
|
|
10245
10067
|
/**
|
|
@@ -10429,9 +10251,8 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
|
|
|
10429
10251
|
/**
|
|
10430
10252
|
* Enables the `tableCellType` attribute for table cells.
|
|
10431
10253
|
*/ function enableCellTypeProperty(editor) {
|
|
10432
|
-
const { model, conversion, editing
|
|
10254
|
+
const { model, conversion, editing } = editor;
|
|
10433
10255
|
const { schema } = model;
|
|
10434
|
-
const scopedHeaders = !!config.get('table.tableCellProperties.scopedHeaders');
|
|
10435
10256
|
const tableUtils = editor.plugins.get(TableUtils);
|
|
10436
10257
|
schema.extend('tableCell', {
|
|
10437
10258
|
allowAttributes: [
|
|
@@ -10454,7 +10275,7 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
|
|
|
10454
10275
|
const { writer } = conversionApi;
|
|
10455
10276
|
const { modelRange } = data;
|
|
10456
10277
|
const modelElement = modelRange?.start.nodeAfter;
|
|
10457
|
-
if (modelElement?.is('element', 'tableCell')
|
|
10278
|
+
if (modelElement?.is('element', 'tableCell')) {
|
|
10458
10279
|
writer.setAttribute('tableCellType', 'header', modelElement);
|
|
10459
10280
|
}
|
|
10460
10281
|
});
|
|
@@ -10466,8 +10287,7 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
|
|
|
10466
10287
|
const modelElement = modelRange?.start.nodeAfter;
|
|
10467
10288
|
if (modelElement?.is('element', 'table') && modelElement.getAttribute('tableType') === 'layout') {
|
|
10468
10289
|
for (const { cell } of new TableWalker(modelElement)){
|
|
10469
|
-
|
|
10470
|
-
if (isTableHeaderCellType(tableCellType)) {
|
|
10290
|
+
if (cell.getAttribute('tableCellType') === 'header') {
|
|
10471
10291
|
writer.setAttribute('tableType', 'content', modelElement);
|
|
10472
10292
|
break;
|
|
10473
10293
|
}
|
|
@@ -10477,55 +10297,6 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
|
|
|
10477
10297
|
priority: priorities.low - 1
|
|
10478
10298
|
});
|
|
10479
10299
|
});
|
|
10480
|
-
// If scoped headers are enabled, add conversion for the `scope` attribute.
|
|
10481
|
-
if (scopedHeaders) {
|
|
10482
|
-
conversion.for('downcast').attributeToAttribute({
|
|
10483
|
-
model: {
|
|
10484
|
-
name: 'tableCell',
|
|
10485
|
-
key: 'tableCellType'
|
|
10486
|
-
},
|
|
10487
|
-
view: (modelAttributeValue)=>{
|
|
10488
|
-
switch(modelAttributeValue){
|
|
10489
|
-
case 'header-row':
|
|
10490
|
-
return {
|
|
10491
|
-
key: 'scope',
|
|
10492
|
-
value: 'row'
|
|
10493
|
-
};
|
|
10494
|
-
case 'header-column':
|
|
10495
|
-
return {
|
|
10496
|
-
key: 'scope',
|
|
10497
|
-
value: 'col'
|
|
10498
|
-
};
|
|
10499
|
-
}
|
|
10500
|
-
}
|
|
10501
|
-
});
|
|
10502
|
-
// Attribute to attribute conversion tend to not override existing `tableCellType` set by other converters.
|
|
10503
|
-
// However, in this scenario if the previous converter set `tableCellType` to `header`, we can adjust it
|
|
10504
|
-
// based on the `scope` attribute.
|
|
10505
|
-
conversion.for('upcast').add((dispatcher)=>{
|
|
10506
|
-
dispatcher.on('element:th', (_, data, conversionApi)=>{
|
|
10507
|
-
const { writer, consumable } = conversionApi;
|
|
10508
|
-
const { viewItem, modelRange } = data;
|
|
10509
|
-
const modelElement = modelRange.start.nodeAfter;
|
|
10510
|
-
const previousTableCellType = modelElement?.getAttribute('tableCellType');
|
|
10511
|
-
if (previousTableCellType === 'header' && consumable.consume(viewItem, {
|
|
10512
|
-
attributes: [
|
|
10513
|
-
'scope'
|
|
10514
|
-
]
|
|
10515
|
-
})) {
|
|
10516
|
-
const scope = viewItem.getAttribute('scope');
|
|
10517
|
-
switch(scope){
|
|
10518
|
-
case 'row':
|
|
10519
|
-
writer.setAttribute('tableCellType', 'header-row', modelElement);
|
|
10520
|
-
break;
|
|
10521
|
-
case 'col':
|
|
10522
|
-
writer.setAttribute('tableCellType', 'header-column', modelElement);
|
|
10523
|
-
break;
|
|
10524
|
-
}
|
|
10525
|
-
}
|
|
10526
|
-
});
|
|
10527
|
-
});
|
|
10528
|
-
}
|
|
10529
10300
|
// Registers a post-fixer that ensures the `headingRows` and `headingColumns` attributes
|
|
10530
10301
|
// are consistent with the `tableCellType` attribute of the cells. `tableCellType` has priority
|
|
10531
10302
|
// over `headingRows` and `headingColumns` and we use it to adjust the heading sections of the table.
|
|
@@ -10583,7 +10354,7 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
|
|
|
10583
10354
|
for (const tableCell of cellsToReconvert){
|
|
10584
10355
|
const viewElement = editing.mapper.toViewElement(tableCell);
|
|
10585
10356
|
const cellType = tableCell.getAttribute('tableCellType');
|
|
10586
|
-
const expectedElementName =
|
|
10357
|
+
const expectedElementName = cellType === 'header' ? 'th' : 'td';
|
|
10587
10358
|
if (viewElement?.name !== expectedElementName) {
|
|
10588
10359
|
editing.reconvertItem(tableCell);
|
|
10589
10360
|
}
|
|
@@ -10714,10 +10485,14 @@ const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/;
|
|
|
10714
10485
|
*/ afterInit() {
|
|
10715
10486
|
const { editor } = this;
|
|
10716
10487
|
const { ui, plugins } = editor;
|
|
10717
|
-
|
|
10488
|
+
let tablePropertiesUI;
|
|
10489
|
+
if (plugins.has('TablePropertiesUIExperimental')) {
|
|
10490
|
+
tablePropertiesUI = plugins.get('TablePropertiesUIExperimental');
|
|
10491
|
+
} else if (plugins.has('TablePropertiesUI')) {
|
|
10492
|
+
tablePropertiesUI = plugins.get('TablePropertiesUI');
|
|
10493
|
+
} else {
|
|
10718
10494
|
return;
|
|
10719
10495
|
}
|
|
10720
|
-
const tablePropertiesUI = plugins.get('TablePropertiesUI');
|
|
10721
10496
|
// Override the default table properties button to include the table type dropdown.
|
|
10722
10497
|
// It needs to be done in `afterInit()` to make sure that `tableProperties` button is
|
|
10723
10498
|
// registered after the initialization of the `TablePropertiesUI`. Otherwise, the
|
|
@@ -12488,7 +12263,7 @@ const TABLE_TYPES = [
|
|
|
12488
12263
|
const defaultTableProperties = getNormalizedDefaultTableProperties(editor.config.get('table.tableProperties.defaultProperties'), {
|
|
12489
12264
|
includeAlignmentProperty: true
|
|
12490
12265
|
});
|
|
12491
|
-
const useInlineStyles = editor.config.get('table.tableProperties.alignment.useInlineStyles')
|
|
12266
|
+
const useInlineStyles = editor.config.get('table.tableProperties.alignment.useInlineStyles') !== false;
|
|
12492
12267
|
editor.data.addStyleProcessorRules(addMarginStylesRules);
|
|
12493
12268
|
editor.data.addStyleProcessorRules(addBorderStylesRules);
|
|
12494
12269
|
enableBorderProperties(editor, {
|
|
@@ -12499,7 +12274,11 @@ const TABLE_TYPES = [
|
|
|
12499
12274
|
editor.commands.add('tableBorderColor', new TableBorderColorCommand(editor, defaultTableProperties.borderColor));
|
|
12500
12275
|
editor.commands.add('tableBorderStyle', new TableBorderStyleCommand(editor, defaultTableProperties.borderStyle));
|
|
12501
12276
|
editor.commands.add('tableBorderWidth', new TableBorderWidthCommand(editor, defaultTableProperties.borderWidth));
|
|
12502
|
-
|
|
12277
|
+
if (editor.config.get('experimentalFlags.useExtendedTableBlockAlignment')) {
|
|
12278
|
+
enableExtendedAlignmentProperty(schema, conversion, defaultTableProperties.alignment, useInlineStyles);
|
|
12279
|
+
} else {
|
|
12280
|
+
enableAlignmentProperty(schema, conversion, defaultTableProperties.alignment);
|
|
12281
|
+
}
|
|
12503
12282
|
editor.commands.add('tableAlignment', new TableAlignmentCommand(editor, defaultTableProperties.alignment));
|
|
12504
12283
|
enableTableToFigureProperty(schema, conversion, {
|
|
12505
12284
|
modelAttribute: 'tableWidth',
|
|
@@ -12526,18 +12305,20 @@ const TABLE_TYPES = [
|
|
|
12526
12305
|
defaultValue: defaultTableProperties.backgroundColor
|
|
12527
12306
|
});
|
|
12528
12307
|
editor.commands.add('tableBackgroundColor', new TableBackgroundColorCommand(editor, defaultTableProperties.backgroundColor));
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
|
|
12308
|
+
if (editor.config.get('experimentalFlags.useExtendedTableBlockAlignment')) {
|
|
12309
|
+
const viewDoc = editor.editing.view.document;
|
|
12310
|
+
// Adjust clipboard output to wrap tables in divs if needed (for alignment).
|
|
12311
|
+
this.listenTo(viewDoc, 'clipboardOutput', (evt, data)=>{
|
|
12312
|
+
editor.editing.view.change((writer)=>{
|
|
12313
|
+
for (const { item } of writer.createRangeIn(data.content)){
|
|
12314
|
+
wrapInDivIfNeeded(item, writer);
|
|
12315
|
+
}
|
|
12316
|
+
data.dataTransfer.setData('text/html', this.editor.data.htmlProcessor.toData(data.content));
|
|
12317
|
+
});
|
|
12318
|
+
}, {
|
|
12319
|
+
priority: 'lowest'
|
|
12537
12320
|
});
|
|
12538
|
-
}
|
|
12539
|
-
priority: 'lowest'
|
|
12540
|
-
});
|
|
12321
|
+
}
|
|
12541
12322
|
}
|
|
12542
12323
|
}
|
|
12543
12324
|
/**
|
|
@@ -12607,10 +12388,10 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
12607
12388
|
});
|
|
12608
12389
|
}
|
|
12609
12390
|
/**
|
|
12610
|
-
* Enables the `'alignment'` attribute for table.
|
|
12391
|
+
* Enables the extended block`'alignment'` attribute for table.
|
|
12611
12392
|
*
|
|
12612
12393
|
* @param defaultValue The default alignment value.
|
|
12613
|
-
*/ function
|
|
12394
|
+
*/ function enableExtendedAlignmentProperty(schema, conversion, defaultValue, useInlineStyles) {
|
|
12614
12395
|
schema.extend('table', {
|
|
12615
12396
|
allowAttributes: [
|
|
12616
12397
|
'tableAlignment'
|
|
@@ -12710,33 +12491,171 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
12710
12491
|
conversion.for('upcast').add(upcastTableAlignedDiv(defaultValue));
|
|
12711
12492
|
}
|
|
12712
12493
|
/**
|
|
12713
|
-
*
|
|
12714
|
-
*
|
|
12715
|
-
* ```html
|
|
12716
|
-
* <div align="right"><table>...</table></div>
|
|
12717
|
-
* <!-- or -->
|
|
12718
|
-
* <div align="center"><table>...</table></div>
|
|
12719
|
-
* <!-- or -->
|
|
12720
|
-
* <div align="left"><table>...</table></div>
|
|
12721
|
-
* ```
|
|
12722
|
-
*
|
|
12723
|
-
* to the model representation:
|
|
12724
|
-
*
|
|
12725
|
-
* ```xml
|
|
12726
|
-
* <table tableAlignment="right|center|left"></table>
|
|
12727
|
-
* ```
|
|
12494
|
+
* Enables the `'alignment'` attribute for table.
|
|
12728
12495
|
*
|
|
12729
|
-
* @
|
|
12730
|
-
*/ function
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
12735
|
-
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12496
|
+
* @param defaultValue The default alignment value.
|
|
12497
|
+
*/ function enableAlignmentProperty(schema, conversion, defaultValue) {
|
|
12498
|
+
const ALIGN_VALUES_REG_EXP = /^(left|center|right)$/;
|
|
12499
|
+
const FLOAT_VALUES_REG_EXP = /^(left|none|right)$/;
|
|
12500
|
+
schema.extend('table', {
|
|
12501
|
+
allowAttributes: [
|
|
12502
|
+
'tableAlignment'
|
|
12503
|
+
]
|
|
12504
|
+
});
|
|
12505
|
+
schema.setAttributeProperties('tableAlignment', {
|
|
12506
|
+
isFormatting: true
|
|
12507
|
+
});
|
|
12508
|
+
conversion.for('downcast').attributeToAttribute({
|
|
12509
|
+
model: {
|
|
12510
|
+
name: 'table',
|
|
12511
|
+
key: 'tableAlignment',
|
|
12512
|
+
values: [
|
|
12513
|
+
'left',
|
|
12514
|
+
'center',
|
|
12515
|
+
'right'
|
|
12516
|
+
]
|
|
12517
|
+
},
|
|
12518
|
+
view: {
|
|
12519
|
+
left: {
|
|
12520
|
+
key: 'style',
|
|
12521
|
+
value: {
|
|
12522
|
+
float: 'left'
|
|
12523
|
+
}
|
|
12524
|
+
},
|
|
12525
|
+
right: {
|
|
12526
|
+
key: 'style',
|
|
12527
|
+
value: {
|
|
12528
|
+
float: 'right'
|
|
12529
|
+
}
|
|
12530
|
+
},
|
|
12531
|
+
center: (alignment, conversionApi, data)=>{
|
|
12532
|
+
const value = data.item.getAttribute('tableType') !== 'layout' ? {
|
|
12533
|
+
// Model: `alignment:center` => CSS: `float:none`.
|
|
12534
|
+
float: 'none'
|
|
12535
|
+
} : {
|
|
12536
|
+
'margin-left': 'auto',
|
|
12537
|
+
'margin-right': 'auto'
|
|
12538
|
+
};
|
|
12539
|
+
return {
|
|
12540
|
+
key: 'style',
|
|
12541
|
+
value
|
|
12542
|
+
};
|
|
12543
|
+
}
|
|
12544
|
+
},
|
|
12545
|
+
converterPriority: 'high'
|
|
12546
|
+
});
|
|
12547
|
+
conversion.for('upcast')// Support for the `float:*;` CSS definition for the table alignment.
|
|
12548
|
+
.attributeToAttribute({
|
|
12549
|
+
view: {
|
|
12550
|
+
name: /^(table|figure)$/,
|
|
12551
|
+
styles: {
|
|
12552
|
+
float: FLOAT_VALUES_REG_EXP
|
|
12553
|
+
}
|
|
12554
|
+
},
|
|
12555
|
+
model: {
|
|
12556
|
+
key: 'tableAlignment',
|
|
12557
|
+
value: (viewElement, conversionApi, data)=>{
|
|
12558
|
+
// Ignore other figure elements.
|
|
12559
|
+
if (viewElement.name == 'figure' && !viewElement.hasClass('table')) {
|
|
12560
|
+
return;
|
|
12561
|
+
}
|
|
12562
|
+
const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
|
|
12563
|
+
let align = viewElement.getStyle('float');
|
|
12564
|
+
// CSS: `float:none` => Model: `alignment:center`.
|
|
12565
|
+
if (align === 'none') {
|
|
12566
|
+
align = 'center';
|
|
12567
|
+
}
|
|
12568
|
+
if (align !== localDefaultValue) {
|
|
12569
|
+
return align;
|
|
12570
|
+
}
|
|
12571
|
+
// Consume the style even if not applied to the element so it won't be processed by other converters.
|
|
12572
|
+
conversionApi.consumable.consume(viewElement, {
|
|
12573
|
+
styles: 'float'
|
|
12574
|
+
});
|
|
12575
|
+
}
|
|
12576
|
+
}
|
|
12577
|
+
})// Support for the `margin-left:auto; margin-right:auto;` CSS definition for the table alignment.
|
|
12578
|
+
.attributeToAttribute({
|
|
12579
|
+
view: {
|
|
12580
|
+
name: /^(table|figure)$/,
|
|
12581
|
+
styles: {
|
|
12582
|
+
'margin-left': 'auto',
|
|
12583
|
+
'margin-right': 'auto'
|
|
12584
|
+
}
|
|
12585
|
+
},
|
|
12586
|
+
model: {
|
|
12587
|
+
key: 'tableAlignment',
|
|
12588
|
+
value: (viewElement, conversionApi, data)=>{
|
|
12589
|
+
// Ignore other figure elements.
|
|
12590
|
+
if (viewElement.name == 'figure' && !viewElement.hasClass('table')) {
|
|
12591
|
+
return;
|
|
12592
|
+
}
|
|
12593
|
+
const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
|
|
12594
|
+
const align = 'center';
|
|
12595
|
+
if (align !== localDefaultValue) {
|
|
12596
|
+
return align;
|
|
12597
|
+
}
|
|
12598
|
+
// Consume the styles even if not applied to the element so it won't be processed by other converters.
|
|
12599
|
+
conversionApi.consumable.consume(viewElement, {
|
|
12600
|
+
styles: [
|
|
12601
|
+
'margin-left',
|
|
12602
|
+
'margin-right'
|
|
12603
|
+
]
|
|
12604
|
+
});
|
|
12605
|
+
}
|
|
12606
|
+
}
|
|
12607
|
+
})// Support for the `align` attribute as the backward compatibility while pasting from other sources.
|
|
12608
|
+
.attributeToAttribute({
|
|
12609
|
+
view: {
|
|
12610
|
+
name: 'table',
|
|
12611
|
+
attributes: {
|
|
12612
|
+
align: ALIGN_VALUES_REG_EXP
|
|
12613
|
+
}
|
|
12614
|
+
},
|
|
12615
|
+
model: {
|
|
12616
|
+
key: 'tableAlignment',
|
|
12617
|
+
value: (viewElement, conversionApi, data)=>{
|
|
12618
|
+
const localDefaultValue = getDefaultValueAdjusted(defaultValue, '', data);
|
|
12619
|
+
const align = viewElement.getAttribute('align');
|
|
12620
|
+
if (align !== localDefaultValue) {
|
|
12621
|
+
return align;
|
|
12622
|
+
}
|
|
12623
|
+
// Consume the attribute even if not applied to the element so it won't be processed by other converters.
|
|
12624
|
+
conversionApi.consumable.consume(viewElement, {
|
|
12625
|
+
attributes: 'align'
|
|
12626
|
+
});
|
|
12627
|
+
}
|
|
12628
|
+
}
|
|
12629
|
+
});
|
|
12630
|
+
}
|
|
12631
|
+
/**
|
|
12632
|
+
* Returns a function that converts the table view representation:
|
|
12633
|
+
*
|
|
12634
|
+
* ```html
|
|
12635
|
+
* <div align="right"><table>...</table></div>
|
|
12636
|
+
* <!-- or -->
|
|
12637
|
+
* <div align="center"><table>...</table></div>
|
|
12638
|
+
* <!-- or -->
|
|
12639
|
+
* <div align="left"><table>...</table></div>
|
|
12640
|
+
* ```
|
|
12641
|
+
*
|
|
12642
|
+
* to the model representation:
|
|
12643
|
+
*
|
|
12644
|
+
* ```xml
|
|
12645
|
+
* <table tableAlignment="right|center|left"></table>
|
|
12646
|
+
* ```
|
|
12647
|
+
*
|
|
12648
|
+
* @internal
|
|
12649
|
+
*/ function upcastTableAlignedDiv(defaultValue) {
|
|
12650
|
+
return (dispatcher)=>{
|
|
12651
|
+
dispatcher.on('element:div', (evt, data, conversionApi)=>{
|
|
12652
|
+
// Do not convert if this is not a "table wrapped in div with align attribute".
|
|
12653
|
+
if (!conversionApi.consumable.test(data.viewItem, {
|
|
12654
|
+
name: true,
|
|
12655
|
+
attributes: 'align'
|
|
12656
|
+
})) {
|
|
12657
|
+
return;
|
|
12658
|
+
}
|
|
12740
12659
|
// Find a table element inside the div element.
|
|
12741
12660
|
const viewTable = getViewTableFromWrapper(data.viewItem);
|
|
12742
12661
|
// Do not convert if table element is absent or was already converted.
|
|
@@ -12899,9 +12818,6 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
12899
12818
|
/**
|
|
12900
12819
|
* The "Cancel" button view.
|
|
12901
12820
|
*/ cancelButtonView;
|
|
12902
|
-
/**
|
|
12903
|
-
* The Back button view displayed in the header.
|
|
12904
|
-
*/ backButtonView;
|
|
12905
12821
|
/**
|
|
12906
12822
|
* A collection of views that can be focused in the form.
|
|
12907
12823
|
*/ _focusables;
|
|
@@ -12943,7 +12859,6 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
12943
12859
|
const { saveButtonView, cancelButtonView } = this._createActionButtons();
|
|
12944
12860
|
this.saveButtonView = saveButtonView;
|
|
12945
12861
|
this.cancelButtonView = cancelButtonView;
|
|
12946
|
-
this.backButtonView = this._createBackButton();
|
|
12947
12862
|
this._focusables = new ViewCollection();
|
|
12948
12863
|
this._focusCycler = new FocusCycler({
|
|
12949
12864
|
focusables: this._focusables,
|
|
@@ -12957,22 +12872,29 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
12957
12872
|
}
|
|
12958
12873
|
});
|
|
12959
12874
|
// Form header.
|
|
12960
|
-
|
|
12875
|
+
this.children.add(new FormHeaderView(locale, {
|
|
12961
12876
|
label: this.t('Table properties')
|
|
12962
|
-
});
|
|
12963
|
-
headerView.children.add(this.backButtonView, 0);
|
|
12964
|
-
this.children.add(headerView);
|
|
12877
|
+
}));
|
|
12965
12878
|
// Border row.
|
|
12966
12879
|
this.children.add(new FormRowView(locale, {
|
|
12967
12880
|
labelView: borderRowLabel,
|
|
12968
12881
|
children: [
|
|
12969
12882
|
borderRowLabel,
|
|
12970
12883
|
borderStyleDropdown,
|
|
12971
|
-
|
|
12972
|
-
|
|
12884
|
+
borderColorInput,
|
|
12885
|
+
borderWidthInput
|
|
12973
12886
|
],
|
|
12974
12887
|
class: 'ck-table-form__border-row'
|
|
12975
12888
|
}));
|
|
12889
|
+
// Background row.
|
|
12890
|
+
this.children.add(new FormRowView(locale, {
|
|
12891
|
+
labelView: backgroundRowLabel,
|
|
12892
|
+
children: [
|
|
12893
|
+
backgroundRowLabel,
|
|
12894
|
+
backgroundInput
|
|
12895
|
+
],
|
|
12896
|
+
class: 'ck-table-form__background-row'
|
|
12897
|
+
}));
|
|
12976
12898
|
this.children.add(new FormRowView(locale, {
|
|
12977
12899
|
children: [
|
|
12978
12900
|
// Dimensions row.
|
|
@@ -12986,31 +12908,22 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
12986
12908
|
],
|
|
12987
12909
|
class: 'ck-table-form__dimensions-row'
|
|
12988
12910
|
}),
|
|
12989
|
-
//
|
|
12911
|
+
// Alignment row.
|
|
12990
12912
|
new FormRowView(locale, {
|
|
12991
|
-
labelView:
|
|
12913
|
+
labelView: alignmentLabel,
|
|
12992
12914
|
children: [
|
|
12993
|
-
|
|
12994
|
-
|
|
12915
|
+
alignmentLabel,
|
|
12916
|
+
alignmentToolbar
|
|
12995
12917
|
],
|
|
12996
|
-
class: 'ck-table-
|
|
12918
|
+
class: 'ck-table-properties-form__alignment-row'
|
|
12997
12919
|
})
|
|
12998
12920
|
]
|
|
12999
12921
|
}));
|
|
13000
|
-
// Alignment row.
|
|
13001
|
-
this.children.add(new FormRowView(locale, {
|
|
13002
|
-
labelView: alignmentLabel,
|
|
13003
|
-
children: [
|
|
13004
|
-
alignmentLabel,
|
|
13005
|
-
alignmentToolbar
|
|
13006
|
-
],
|
|
13007
|
-
class: 'ck-table-properties-form__alignment-row'
|
|
13008
|
-
}));
|
|
13009
12922
|
// Action row.
|
|
13010
12923
|
this.children.add(new FormRowView(locale, {
|
|
13011
12924
|
children: [
|
|
13012
|
-
this.
|
|
13013
|
-
this.
|
|
12925
|
+
this.saveButtonView,
|
|
12926
|
+
this.cancelButtonView
|
|
13014
12927
|
],
|
|
13015
12928
|
class: 'ck-table-form__action-row'
|
|
13016
12929
|
}));
|
|
@@ -13047,15 +12960,14 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13047
12960
|
});
|
|
13048
12961
|
[
|
|
13049
12962
|
this.borderStyleDropdown,
|
|
13050
|
-
this.borderWidthInput,
|
|
13051
12963
|
this.borderColorInput,
|
|
12964
|
+
this.borderWidthInput,
|
|
12965
|
+
this.backgroundInput,
|
|
13052
12966
|
this.widthInput,
|
|
13053
12967
|
this.heightInput,
|
|
13054
|
-
this.backgroundInput,
|
|
13055
12968
|
this.alignmentToolbar,
|
|
13056
|
-
this.cancelButtonView,
|
|
13057
12969
|
this.saveButtonView,
|
|
13058
|
-
this.
|
|
12970
|
+
this.cancelButtonView
|
|
13059
12971
|
].forEach((view)=>{
|
|
13060
12972
|
// Register the view as focusable.
|
|
13061
12973
|
this._focusables.add(view);
|
|
@@ -13090,7 +13002,7 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13090
13002
|
width: defaultTableProperties.borderWidth,
|
|
13091
13003
|
color: defaultTableProperties.borderColor
|
|
13092
13004
|
};
|
|
13093
|
-
const colorInputCreator = getLabeledColorInputCreator({
|
|
13005
|
+
const colorInputCreator = getLabeledColorInputCreator$1({
|
|
13094
13006
|
colorConfig: this.options.borderColors,
|
|
13095
13007
|
columns: 5,
|
|
13096
13008
|
defaultColorValue: defaultBorder.color,
|
|
@@ -13103,7 +13015,7 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13103
13015
|
const borderRowLabel = new LabelView(locale);
|
|
13104
13016
|
borderRowLabel.text = t('Border');
|
|
13105
13017
|
// -- Style ---------------------------------------------------
|
|
13106
|
-
const styleLabels = getBorderStyleLabels(t);
|
|
13018
|
+
const styleLabels = getBorderStyleLabels$1(t);
|
|
13107
13019
|
const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
|
|
13108
13020
|
borderStyleDropdown.set({
|
|
13109
13021
|
label: accessibleLabel,
|
|
@@ -13123,7 +13035,7 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13123
13035
|
this.borderStyle = evt.source._borderStyleValue;
|
|
13124
13036
|
});
|
|
13125
13037
|
borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
|
|
13126
|
-
addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
|
|
13038
|
+
addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions$1(this, defaultBorder.style), {
|
|
13127
13039
|
role: 'menu',
|
|
13128
13040
|
ariaLabel: accessibleLabel
|
|
13129
13041
|
});
|
|
@@ -13134,7 +13046,7 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13134
13046
|
class: 'ck-table-form__border-width'
|
|
13135
13047
|
});
|
|
13136
13048
|
borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
|
|
13137
|
-
borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
|
|
13049
|
+
borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$2);
|
|
13138
13050
|
borderWidthInput.fieldView.on('input', ()=>{
|
|
13139
13051
|
this.borderWidth = borderWidthInput.fieldView.element.value;
|
|
13140
13052
|
});
|
|
@@ -13145,7 +13057,7 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13145
13057
|
class: 'ck-table-form__border-color'
|
|
13146
13058
|
});
|
|
13147
13059
|
borderColorInput.fieldView.bind('value').to(this, 'borderColor');
|
|
13148
|
-
borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
|
|
13060
|
+
borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$2);
|
|
13149
13061
|
borderColorInput.fieldView.on('input', ()=>{
|
|
13150
13062
|
this.borderColor = borderColorInput.fieldView.value;
|
|
13151
13063
|
});
|
|
@@ -13153,12 +13065,12 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13153
13065
|
this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
|
|
13154
13066
|
// When removing the border (`border-style:none`), clear the remaining `border-*` properties.
|
|
13155
13067
|
// See: https://github.com/ckeditor/ckeditor5/issues/6227.
|
|
13156
|
-
if (!isBorderStyleSet(newValue)) {
|
|
13068
|
+
if (!isBorderStyleSet$2(newValue)) {
|
|
13157
13069
|
this.borderColor = '';
|
|
13158
13070
|
this.borderWidth = '';
|
|
13159
13071
|
}
|
|
13160
13072
|
// When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
|
|
13161
|
-
if (!isBorderStyleSet(oldValue)) {
|
|
13073
|
+
if (!isBorderStyleSet$2(oldValue)) {
|
|
13162
13074
|
this.borderColor = defaultBorder.color;
|
|
13163
13075
|
this.borderWidth = defaultBorder.width;
|
|
13164
13076
|
}
|
|
@@ -13181,7 +13093,7 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13181
13093
|
const backgroundRowLabel = new LabelView(locale);
|
|
13182
13094
|
backgroundRowLabel.text = t('Background');
|
|
13183
13095
|
// -- Background color input -----------------------------------
|
|
13184
|
-
const backgroundInputCreator = getLabeledColorInputCreator({
|
|
13096
|
+
const backgroundInputCreator = getLabeledColorInputCreator$1({
|
|
13185
13097
|
colorConfig: this.options.backgroundColors,
|
|
13186
13098
|
columns: 5,
|
|
13187
13099
|
defaultColorValue: this.options.defaultTableProperties.backgroundColor,
|
|
@@ -13263,7 +13175,7 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13263
13175
|
const t = this.t;
|
|
13264
13176
|
// -- Label ---------------------------------------------------
|
|
13265
13177
|
const alignmentLabel = new LabelView(locale);
|
|
13266
|
-
alignmentLabel.text = t('
|
|
13178
|
+
alignmentLabel.text = t('Alignment');
|
|
13267
13179
|
// -- Toolbar ---------------------------------------------------
|
|
13268
13180
|
const alignmentToolbar = new ToolbarView(locale);
|
|
13269
13181
|
alignmentToolbar.set({
|
|
@@ -13271,14 +13183,12 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13271
13183
|
isCompact: true,
|
|
13272
13184
|
ariaLabel: t('Table alignment toolbar')
|
|
13273
13185
|
});
|
|
13274
|
-
fillToolbar({
|
|
13186
|
+
fillToolbar$1({
|
|
13275
13187
|
view: this,
|
|
13276
13188
|
icons: {
|
|
13277
13189
|
left: IconObjectInlineLeft,
|
|
13278
13190
|
center: IconObjectCenter,
|
|
13279
|
-
right: IconObjectInlineRight
|
|
13280
|
-
blockLeft: IconObjectLeft,
|
|
13281
|
-
blockRight: IconObjectRight
|
|
13191
|
+
right: IconObjectInlineRight
|
|
13282
13192
|
},
|
|
13283
13193
|
toolbar: alignmentToolbar,
|
|
13284
13194
|
labels: this._alignmentLabels,
|
|
@@ -13309,7 +13219,8 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13309
13219
|
];
|
|
13310
13220
|
saveButtonView.set({
|
|
13311
13221
|
label: t('Save'),
|
|
13312
|
-
|
|
13222
|
+
icon: IconCheck,
|
|
13223
|
+
class: 'ck-button-save',
|
|
13313
13224
|
type: 'submit',
|
|
13314
13225
|
withText: true
|
|
13315
13226
|
});
|
|
@@ -13318,6 +13229,8 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13318
13229
|
});
|
|
13319
13230
|
cancelButtonView.set({
|
|
13320
13231
|
label: t('Cancel'),
|
|
13232
|
+
icon: IconCancel,
|
|
13233
|
+
class: 'ck-button-cancel',
|
|
13321
13234
|
withText: true
|
|
13322
13235
|
});
|
|
13323
13236
|
cancelButtonView.delegate('execute').to(this, 'cancel');
|
|
@@ -13326,56 +13239,37 @@ function insertWrapperWithAlignment(writer, align, table) {
|
|
|
13326
13239
|
cancelButtonView
|
|
13327
13240
|
};
|
|
13328
13241
|
}
|
|
13329
|
-
/**
|
|
13330
|
-
* Creates a back button view that cancels the form.
|
|
13331
|
-
*/ _createBackButton() {
|
|
13332
|
-
const t = this.locale.t;
|
|
13333
|
-
const backButton = new ButtonView(this.locale);
|
|
13334
|
-
backButton.set({
|
|
13335
|
-
class: 'ck-button-back',
|
|
13336
|
-
label: t('Back'),
|
|
13337
|
-
icon: IconPreviousArrow,
|
|
13338
|
-
tooltip: true
|
|
13339
|
-
});
|
|
13340
|
-
backButton.delegate('execute').to(this, 'cancel');
|
|
13341
|
-
return backButton;
|
|
13342
|
-
}
|
|
13343
13242
|
/**
|
|
13344
13243
|
* Provides localized labels for {@link #alignmentToolbar} buttons.
|
|
13345
13244
|
*/ get _alignmentLabels() {
|
|
13346
13245
|
const locale = this.locale;
|
|
13347
13246
|
const t = this.t;
|
|
13348
|
-
const
|
|
13349
|
-
const
|
|
13350
|
-
const
|
|
13351
|
-
const center = t('Center table with no text wrapping');
|
|
13352
|
-
const right = t('Align table to the right with text wrapping');
|
|
13247
|
+
const left = t('Align table to the left');
|
|
13248
|
+
const center = t('Center table');
|
|
13249
|
+
const right = t('Align table to the right');
|
|
13353
13250
|
// Returns object with a proper order of labels.
|
|
13354
13251
|
if (locale.uiLanguageDirection === 'rtl') {
|
|
13355
13252
|
return {
|
|
13356
13253
|
right,
|
|
13254
|
+
center,
|
|
13255
|
+
left
|
|
13256
|
+
};
|
|
13257
|
+
} else {
|
|
13258
|
+
return {
|
|
13357
13259
|
left,
|
|
13358
|
-
blockRight,
|
|
13359
13260
|
center,
|
|
13360
|
-
|
|
13261
|
+
right
|
|
13361
13262
|
};
|
|
13362
13263
|
}
|
|
13363
|
-
return {
|
|
13364
|
-
blockLeft,
|
|
13365
|
-
center,
|
|
13366
|
-
blockRight,
|
|
13367
|
-
left,
|
|
13368
|
-
right
|
|
13369
|
-
};
|
|
13370
13264
|
}
|
|
13371
13265
|
}
|
|
13372
|
-
function isBorderStyleSet(value) {
|
|
13266
|
+
function isBorderStyleSet$2(value) {
|
|
13373
13267
|
return value !== 'none';
|
|
13374
13268
|
}
|
|
13375
13269
|
|
|
13376
|
-
const ERROR_TEXT_TIMEOUT = 500;
|
|
13270
|
+
const ERROR_TEXT_TIMEOUT$2 = 500;
|
|
13377
13271
|
// Map of view properties and related commands.
|
|
13378
|
-
const propertyToCommandMap = {
|
|
13272
|
+
const propertyToCommandMap$2 = {
|
|
13379
13273
|
borderStyle: 'tableBorderStyle',
|
|
13380
13274
|
borderColor: 'tableBorderColor',
|
|
13381
13275
|
borderWidth: 'tableBorderWidth',
|
|
@@ -13467,7 +13361,7 @@ const propertyToCommandMap = {
|
|
|
13467
13361
|
tooltip: true
|
|
13468
13362
|
});
|
|
13469
13363
|
this.listenTo(view, 'execute', ()=>this._showView());
|
|
13470
|
-
const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName));
|
|
13364
|
+
const commands = Object.values(propertyToCommandMap$2).map((commandName)=>editor.commands.get(commandName));
|
|
13471
13365
|
view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
|
|
13472
13366
|
return view;
|
|
13473
13367
|
}
|
|
@@ -13577,7 +13471,7 @@ const propertyToCommandMap = {
|
|
|
13577
13471
|
*/ _fillViewFormFromCommandValues() {
|
|
13578
13472
|
const commands = this.editor.commands;
|
|
13579
13473
|
const borderStyleCommand = commands.get('tableBorderStyle');
|
|
13580
|
-
Object.entries(propertyToCommandMap).map(([property, commandName])=>{
|
|
13474
|
+
Object.entries(propertyToCommandMap$2).map(([property, commandName])=>{
|
|
13581
13475
|
const propertyKey = property;
|
|
13582
13476
|
const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableProperties[propertyKey] || '' : this._defaultLayoutTableProperties[propertyKey] || '';
|
|
13583
13477
|
return [
|
|
@@ -13686,7 +13580,7 @@ const propertyToCommandMap = {
|
|
|
13686
13580
|
const { commandName, viewField, validator, errorText } = options;
|
|
13687
13581
|
const setErrorTextDebounced = debounce(()=>{
|
|
13688
13582
|
viewField.errorText = errorText;
|
|
13689
|
-
}, ERROR_TEXT_TIMEOUT);
|
|
13583
|
+
}, ERROR_TEXT_TIMEOUT$2);
|
|
13690
13584
|
return (evt, propertyName, newValue)=>{
|
|
13691
13585
|
setErrorTextDebounced.cancel();
|
|
13692
13586
|
// Do not execute the command on initial call (opening the table properties view).
|
|
@@ -14127,5 +14021,2096 @@ const propertyToCommandMap = {
|
|
|
14127
14021
|
}
|
|
14128
14022
|
}
|
|
14129
14023
|
|
|
14130
|
-
|
|
14024
|
+
/**
|
|
14025
|
+
* Returns an object containing pairs of CSS border style values and their localized UI
|
|
14026
|
+
* labels. Used by {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView}
|
|
14027
|
+
* and {@link module:table/tableproperties/ui/tablepropertiesview~TablePropertiesView}.
|
|
14028
|
+
*
|
|
14029
|
+
* @internal
|
|
14030
|
+
* @param t The "t" function provided by the editor that is used to localize strings.
|
|
14031
|
+
*/ function getBorderStyleLabels(t) {
|
|
14032
|
+
return {
|
|
14033
|
+
none: t('None'),
|
|
14034
|
+
solid: t('Solid'),
|
|
14035
|
+
dotted: t('Dotted'),
|
|
14036
|
+
dashed: t('Dashed'),
|
|
14037
|
+
double: t('Double'),
|
|
14038
|
+
groove: t('Groove'),
|
|
14039
|
+
ridge: t('Ridge'),
|
|
14040
|
+
inset: t('Inset'),
|
|
14041
|
+
outset: t('Outset')
|
|
14042
|
+
};
|
|
14043
|
+
}
|
|
14044
|
+
/**
|
|
14045
|
+
* Generates item definitions for a UI dropdown that allows changing the border style of a table or a table cell.
|
|
14046
|
+
*
|
|
14047
|
+
* @internal
|
|
14048
|
+
* @param defaultStyle The default border.
|
|
14049
|
+
*/ function getBorderStyleDefinitions(view, defaultStyle) {
|
|
14050
|
+
const itemDefinitions = new Collection();
|
|
14051
|
+
const styleLabels = getBorderStyleLabels(view.t);
|
|
14052
|
+
for(const style in styleLabels){
|
|
14053
|
+
const definition = {
|
|
14054
|
+
type: 'button',
|
|
14055
|
+
model: new UIModel({
|
|
14056
|
+
_borderStyleValue: style,
|
|
14057
|
+
label: styleLabels[style],
|
|
14058
|
+
role: 'menuitemradio',
|
|
14059
|
+
withText: true
|
|
14060
|
+
})
|
|
14061
|
+
};
|
|
14062
|
+
if (style === 'none') {
|
|
14063
|
+
definition.model.bind('isOn').to(view, 'borderStyle', (value)=>{
|
|
14064
|
+
if (defaultStyle === 'none') {
|
|
14065
|
+
return !value;
|
|
14066
|
+
}
|
|
14067
|
+
return value === style;
|
|
14068
|
+
});
|
|
14069
|
+
} else {
|
|
14070
|
+
definition.model.bind('isOn').to(view, 'borderStyle', (value)=>{
|
|
14071
|
+
return value === style;
|
|
14072
|
+
});
|
|
14073
|
+
}
|
|
14074
|
+
itemDefinitions.add(definition);
|
|
14075
|
+
}
|
|
14076
|
+
return itemDefinitions;
|
|
14077
|
+
}
|
|
14078
|
+
/**
|
|
14079
|
+
* A helper that fills a toolbar with buttons that:
|
|
14080
|
+
*
|
|
14081
|
+
* * have some labels,
|
|
14082
|
+
* * have some icons,
|
|
14083
|
+
* * set a certain UI view property value upon execution.
|
|
14084
|
+
*
|
|
14085
|
+
* @internal
|
|
14086
|
+
* @param options Configuration options
|
|
14087
|
+
* @param options.view The view that has the observable property.
|
|
14088
|
+
* @param options.icons Object with button icons.
|
|
14089
|
+
* @param options.toolbar The toolbar to fill with buttons.
|
|
14090
|
+
* @param options.labels Object with button labels.
|
|
14091
|
+
* @param options.propertyName The name of the observable property in the view.
|
|
14092
|
+
* @param options.nameToValue A function that maps a button name to a value. By default names are the same as values.
|
|
14093
|
+
* @param options.defaultValue Default value for the property.
|
|
14094
|
+
*/ function fillToolbar(options) {
|
|
14095
|
+
const { view, icons, toolbar, labels, propertyName, nameToValue, defaultValue } = options;
|
|
14096
|
+
for(const name in labels){
|
|
14097
|
+
const button = new ButtonView(view.locale);
|
|
14098
|
+
button.set({
|
|
14099
|
+
role: 'radio',
|
|
14100
|
+
isToggleable: true,
|
|
14101
|
+
label: labels[name],
|
|
14102
|
+
icon: icons[name],
|
|
14103
|
+
tooltip: labels[name]
|
|
14104
|
+
});
|
|
14105
|
+
// If specified the `nameToValue()` callback, map the value based on the option's name.
|
|
14106
|
+
const buttonValue = nameToValue ? nameToValue(name) : name;
|
|
14107
|
+
button.bind('isOn').to(view, propertyName, (value)=>{
|
|
14108
|
+
// `value` comes from `view[ propertyName ]`.
|
|
14109
|
+
let valueToCompare = value;
|
|
14110
|
+
// If it's empty, and the `defaultValue` is specified, use it instead.
|
|
14111
|
+
if (value === '' && defaultValue) {
|
|
14112
|
+
valueToCompare = defaultValue;
|
|
14113
|
+
}
|
|
14114
|
+
return buttonValue === valueToCompare;
|
|
14115
|
+
});
|
|
14116
|
+
button.on('execute', ()=>{
|
|
14117
|
+
// Allow toggling alignment if there is no default value specified (especially for layout tables).
|
|
14118
|
+
if (!defaultValue && buttonValue && view[propertyName] === buttonValue) {
|
|
14119
|
+
view[propertyName] = undefined;
|
|
14120
|
+
} else {
|
|
14121
|
+
view[propertyName] = buttonValue;
|
|
14122
|
+
}
|
|
14123
|
+
});
|
|
14124
|
+
toolbar.items.add(button);
|
|
14125
|
+
}
|
|
14126
|
+
}
|
|
14127
|
+
/**
|
|
14128
|
+
* Returns a creator for a color input with a label.
|
|
14129
|
+
*
|
|
14130
|
+
* For given options, it returns a function that creates an instance of a
|
|
14131
|
+
* {@link module:table/ui/colorinputview~ColorInputView color input} logically related to
|
|
14132
|
+
* a {@link module:ui/labeledfield/labeledfieldview~LabeledFieldView labeled view} in the DOM.
|
|
14133
|
+
*
|
|
14134
|
+
* The helper does the following:
|
|
14135
|
+
*
|
|
14136
|
+
* * It sets the color input `id` and `ariaDescribedById` attributes.
|
|
14137
|
+
* * It binds the color input `isReadOnly` to the labeled view.
|
|
14138
|
+
* * It binds the color input `hasError` to the labeled view.
|
|
14139
|
+
* * It enables a logic that cleans up the error when the user starts typing in the color input.
|
|
14140
|
+
*
|
|
14141
|
+
* Usage:
|
|
14142
|
+
*
|
|
14143
|
+
* ```ts
|
|
14144
|
+
* const colorInputCreator = getLabeledColorInputCreator( {
|
|
14145
|
+
* colorConfig: [ ... ],
|
|
14146
|
+
* columns: 3,
|
|
14147
|
+
* } );
|
|
14148
|
+
*
|
|
14149
|
+
* const labeledInputView = new LabeledFieldView( locale, colorInputCreator );
|
|
14150
|
+
* console.log( labeledInputView.view ); // A color input instance.
|
|
14151
|
+
* ```
|
|
14152
|
+
*
|
|
14153
|
+
* @internal
|
|
14154
|
+
* @param options Color input options.
|
|
14155
|
+
* @param options.colorConfig The configuration of the color palette displayed in the input's dropdown.
|
|
14156
|
+
* @param options.columns The configuration of the number of columns the color palette consists of in the input's dropdown.
|
|
14157
|
+
* @param options.defaultColorValue If specified, the color input view will replace the "Remove color" button with
|
|
14158
|
+
* the "Restore default" button. Instead of clearing the input field, the default color value will be set.
|
|
14159
|
+
* @param options.colorPickerConfig The configuration of the color picker. You could disable it or define your output format.
|
|
14160
|
+
*/ function getLabeledColorInputCreator(options) {
|
|
14161
|
+
return (labeledFieldView, viewUid, statusUid)=>{
|
|
14162
|
+
const colorInputView = new ColorInputView(labeledFieldView.locale, {
|
|
14163
|
+
colorDefinitions: colorConfigToColorGridDefinitions(options.colorConfig),
|
|
14164
|
+
columns: options.columns,
|
|
14165
|
+
defaultColorValue: options.defaultColorValue,
|
|
14166
|
+
colorPickerConfig: options.colorPickerConfig
|
|
14167
|
+
});
|
|
14168
|
+
colorInputView.inputView.set({
|
|
14169
|
+
id: viewUid,
|
|
14170
|
+
ariaDescribedById: statusUid
|
|
14171
|
+
});
|
|
14172
|
+
colorInputView.bind('isReadOnly').to(labeledFieldView, 'isEnabled', (value)=>!value);
|
|
14173
|
+
colorInputView.bind('hasError').to(labeledFieldView, 'errorText', (value)=>!!value);
|
|
14174
|
+
colorInputView.on('input', ()=>{
|
|
14175
|
+
// UX: Make the error text disappear and disable the error indicator as the user
|
|
14176
|
+
// starts fixing the errors.
|
|
14177
|
+
labeledFieldView.errorText = null;
|
|
14178
|
+
});
|
|
14179
|
+
labeledFieldView.bind('isEmpty', 'isFocused').to(colorInputView);
|
|
14180
|
+
return colorInputView;
|
|
14181
|
+
};
|
|
14182
|
+
}
|
|
14183
|
+
function colorConfigToColorGridDefinitions(colorConfig) {
|
|
14184
|
+
return colorConfig.map((item)=>({
|
|
14185
|
+
color: item.model,
|
|
14186
|
+
label: item.label,
|
|
14187
|
+
options: {
|
|
14188
|
+
hasBorder: item.hasBorder
|
|
14189
|
+
}
|
|
14190
|
+
}));
|
|
14191
|
+
}
|
|
14192
|
+
|
|
14193
|
+
/**
|
|
14194
|
+
* The class representing a table properties form, allowing users to customize
|
|
14195
|
+
* certain style aspects of a table, for instance, border, background color, alignment, etc..
|
|
14196
|
+
*/ class TablePropertiesViewExperimental extends View {
|
|
14197
|
+
/**
|
|
14198
|
+
* Options passed to the view. See {@link #constructor} to learn more.
|
|
14199
|
+
*/ options;
|
|
14200
|
+
/**
|
|
14201
|
+
* Tracks information about the DOM focus in the form.
|
|
14202
|
+
*/ focusTracker;
|
|
14203
|
+
/**
|
|
14204
|
+
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
|
14205
|
+
*/ keystrokes;
|
|
14206
|
+
/**
|
|
14207
|
+
* A collection of child views in the form.
|
|
14208
|
+
*/ children;
|
|
14209
|
+
/**
|
|
14210
|
+
* A dropdown that allows selecting the style of the table border.
|
|
14211
|
+
*/ borderStyleDropdown;
|
|
14212
|
+
/**
|
|
14213
|
+
* An input that allows specifying the width of the table border.
|
|
14214
|
+
*/ borderWidthInput;
|
|
14215
|
+
/**
|
|
14216
|
+
* An input that allows specifying the color of the table border.
|
|
14217
|
+
*/ borderColorInput;
|
|
14218
|
+
/**
|
|
14219
|
+
* An input that allows specifying the table background color.
|
|
14220
|
+
*/ backgroundInput;
|
|
14221
|
+
/**
|
|
14222
|
+
* An input that allows specifying the table width.
|
|
14223
|
+
*/ widthInput;
|
|
14224
|
+
/**
|
|
14225
|
+
* An input that allows specifying the table height.
|
|
14226
|
+
*/ heightInput;
|
|
14227
|
+
/**
|
|
14228
|
+
* A toolbar with buttons that allow changing the alignment of an entire table.
|
|
14229
|
+
*/ alignmentToolbar;
|
|
14230
|
+
/**
|
|
14231
|
+
* The "Save" button view.
|
|
14232
|
+
*/ saveButtonView;
|
|
14233
|
+
/**
|
|
14234
|
+
* The "Cancel" button view.
|
|
14235
|
+
*/ cancelButtonView;
|
|
14236
|
+
/**
|
|
14237
|
+
* The Back button view displayed in the header.
|
|
14238
|
+
*/ backButtonView;
|
|
14239
|
+
/**
|
|
14240
|
+
* A collection of views that can be focused in the form.
|
|
14241
|
+
*/ _focusables;
|
|
14242
|
+
/**
|
|
14243
|
+
* Helps cycling over {@link #_focusables} in the form.
|
|
14244
|
+
*/ _focusCycler;
|
|
14245
|
+
/**
|
|
14246
|
+
* @param locale The {@link module:core/editor/editor~Editor#locale} instance.
|
|
14247
|
+
* @param options Additional configuration of the view.
|
|
14248
|
+
*/ constructor(locale, options){
|
|
14249
|
+
super(locale);
|
|
14250
|
+
this.set({
|
|
14251
|
+
borderStyle: '',
|
|
14252
|
+
borderWidth: '',
|
|
14253
|
+
borderColor: '',
|
|
14254
|
+
backgroundColor: '',
|
|
14255
|
+
width: '',
|
|
14256
|
+
height: '',
|
|
14257
|
+
alignment: ''
|
|
14258
|
+
});
|
|
14259
|
+
this.options = options;
|
|
14260
|
+
const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
|
|
14261
|
+
const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
|
|
14262
|
+
const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
|
|
14263
|
+
const { alignmentToolbar, alignmentLabel } = this._createAlignmentFields();
|
|
14264
|
+
this.focusTracker = new FocusTracker();
|
|
14265
|
+
this.keystrokes = new KeystrokeHandler();
|
|
14266
|
+
this.children = this.createCollection();
|
|
14267
|
+
this.borderStyleDropdown = borderStyleDropdown;
|
|
14268
|
+
this.borderWidthInput = borderWidthInput;
|
|
14269
|
+
this.borderColorInput = borderColorInput;
|
|
14270
|
+
this.backgroundInput = backgroundInput;
|
|
14271
|
+
this.widthInput = widthInput;
|
|
14272
|
+
this.heightInput = heightInput;
|
|
14273
|
+
this.alignmentToolbar = alignmentToolbar;
|
|
14274
|
+
// Defer creating to make sure other fields are present and the Save button can
|
|
14275
|
+
// bind its #isEnabled to their error messages so there's no way to save unless all
|
|
14276
|
+
// fields are valid.
|
|
14277
|
+
const { saveButtonView, cancelButtonView } = this._createActionButtons();
|
|
14278
|
+
this.saveButtonView = saveButtonView;
|
|
14279
|
+
this.cancelButtonView = cancelButtonView;
|
|
14280
|
+
this.backButtonView = this._createBackButton();
|
|
14281
|
+
this._focusables = new ViewCollection();
|
|
14282
|
+
this._focusCycler = new FocusCycler({
|
|
14283
|
+
focusables: this._focusables,
|
|
14284
|
+
focusTracker: this.focusTracker,
|
|
14285
|
+
keystrokeHandler: this.keystrokes,
|
|
14286
|
+
actions: {
|
|
14287
|
+
// Navigate form fields backwards using the Shift + Tab keystroke.
|
|
14288
|
+
focusPrevious: 'shift + tab',
|
|
14289
|
+
// Navigate form fields forwards using the Tab key.
|
|
14290
|
+
focusNext: 'tab'
|
|
14291
|
+
}
|
|
14292
|
+
});
|
|
14293
|
+
// Form header.
|
|
14294
|
+
const headerView = new FormHeaderView(locale, {
|
|
14295
|
+
label: this.t('Table properties')
|
|
14296
|
+
});
|
|
14297
|
+
headerView.children.add(this.backButtonView, 0);
|
|
14298
|
+
this.children.add(headerView);
|
|
14299
|
+
// Border row.
|
|
14300
|
+
this.children.add(new FormRowView(locale, {
|
|
14301
|
+
labelView: borderRowLabel,
|
|
14302
|
+
children: [
|
|
14303
|
+
borderRowLabel,
|
|
14304
|
+
borderStyleDropdown,
|
|
14305
|
+
borderWidthInput,
|
|
14306
|
+
borderColorInput
|
|
14307
|
+
],
|
|
14308
|
+
class: 'ck-table-form__border-row'
|
|
14309
|
+
}));
|
|
14310
|
+
this.children.add(new FormRowView(locale, {
|
|
14311
|
+
children: [
|
|
14312
|
+
// Dimensions row.
|
|
14313
|
+
new FormRowView(locale, {
|
|
14314
|
+
labelView: dimensionsLabel,
|
|
14315
|
+
children: [
|
|
14316
|
+
dimensionsLabel,
|
|
14317
|
+
widthInput,
|
|
14318
|
+
operatorLabel,
|
|
14319
|
+
heightInput
|
|
14320
|
+
],
|
|
14321
|
+
class: 'ck-table-form__dimensions-row'
|
|
14322
|
+
}),
|
|
14323
|
+
// Background row.
|
|
14324
|
+
new FormRowView(locale, {
|
|
14325
|
+
labelView: backgroundRowLabel,
|
|
14326
|
+
children: [
|
|
14327
|
+
backgroundRowLabel,
|
|
14328
|
+
backgroundInput
|
|
14329
|
+
],
|
|
14330
|
+
class: 'ck-table-form__background-row'
|
|
14331
|
+
})
|
|
14332
|
+
]
|
|
14333
|
+
}));
|
|
14334
|
+
// Alignment row.
|
|
14335
|
+
this.children.add(new FormRowView(locale, {
|
|
14336
|
+
labelView: alignmentLabel,
|
|
14337
|
+
children: [
|
|
14338
|
+
alignmentLabel,
|
|
14339
|
+
alignmentToolbar
|
|
14340
|
+
],
|
|
14341
|
+
class: 'ck-table-properties-form__alignment-row'
|
|
14342
|
+
}));
|
|
14343
|
+
// Action row.
|
|
14344
|
+
this.children.add(new FormRowView(locale, {
|
|
14345
|
+
children: [
|
|
14346
|
+
this.cancelButtonView,
|
|
14347
|
+
this.saveButtonView
|
|
14348
|
+
],
|
|
14349
|
+
class: 'ck-table-form__action-row'
|
|
14350
|
+
}));
|
|
14351
|
+
this.setTemplate({
|
|
14352
|
+
tag: 'form',
|
|
14353
|
+
attributes: {
|
|
14354
|
+
class: [
|
|
14355
|
+
'ck',
|
|
14356
|
+
'ck-form',
|
|
14357
|
+
'ck-table-form',
|
|
14358
|
+
'ck-table-properties-form',
|
|
14359
|
+
'ck-table-properties-form_experimental'
|
|
14360
|
+
],
|
|
14361
|
+
// https://github.com/ckeditor/ckeditor5-link/issues/90
|
|
14362
|
+
tabindex: '-1'
|
|
14363
|
+
},
|
|
14364
|
+
children: this.children
|
|
14365
|
+
});
|
|
14366
|
+
}
|
|
14367
|
+
/**
|
|
14368
|
+
* @inheritDoc
|
|
14369
|
+
*/ render() {
|
|
14370
|
+
super.render();
|
|
14371
|
+
// Enable the "submit" event for this view. It can be triggered by the #saveButtonView
|
|
14372
|
+
// which is of the "submit" DOM "type".
|
|
14373
|
+
submitHandler({
|
|
14374
|
+
view: this
|
|
14375
|
+
});
|
|
14376
|
+
// Maintain continuous focus cycling over views that have focusable children and focus cyclers themselves.
|
|
14377
|
+
[
|
|
14378
|
+
this.borderColorInput,
|
|
14379
|
+
this.backgroundInput
|
|
14380
|
+
].forEach((view)=>{
|
|
14381
|
+
this._focusCycler.chain(view.fieldView.focusCycler);
|
|
14382
|
+
});
|
|
14383
|
+
[
|
|
14384
|
+
this.borderStyleDropdown,
|
|
14385
|
+
this.borderWidthInput,
|
|
14386
|
+
this.borderColorInput,
|
|
14387
|
+
this.widthInput,
|
|
14388
|
+
this.heightInput,
|
|
14389
|
+
this.backgroundInput,
|
|
14390
|
+
this.alignmentToolbar,
|
|
14391
|
+
this.cancelButtonView,
|
|
14392
|
+
this.saveButtonView,
|
|
14393
|
+
this.backButtonView
|
|
14394
|
+
].forEach((view)=>{
|
|
14395
|
+
// Register the view as focusable.
|
|
14396
|
+
this._focusables.add(view);
|
|
14397
|
+
// Register the view in the focus tracker.
|
|
14398
|
+
this.focusTracker.add(view.element);
|
|
14399
|
+
});
|
|
14400
|
+
// Mainly for closing using "Esc" and navigation using "Tab".
|
|
14401
|
+
this.keystrokes.listenTo(this.element);
|
|
14402
|
+
}
|
|
14403
|
+
/**
|
|
14404
|
+
* @inheritDoc
|
|
14405
|
+
*/ destroy() {
|
|
14406
|
+
super.destroy();
|
|
14407
|
+
this.focusTracker.destroy();
|
|
14408
|
+
this.keystrokes.destroy();
|
|
14409
|
+
}
|
|
14410
|
+
/**
|
|
14411
|
+
* Focuses the fist focusable field in the form.
|
|
14412
|
+
*/ focus() {
|
|
14413
|
+
this._focusCycler.focusFirst();
|
|
14414
|
+
}
|
|
14415
|
+
/**
|
|
14416
|
+
* Creates the following form fields:
|
|
14417
|
+
*
|
|
14418
|
+
* * {@link #borderStyleDropdown},
|
|
14419
|
+
* * {@link #borderWidthInput},
|
|
14420
|
+
* * {@link #borderColorInput}.
|
|
14421
|
+
*/ _createBorderFields() {
|
|
14422
|
+
const defaultTableProperties = this.options.defaultTableProperties;
|
|
14423
|
+
const defaultBorder = {
|
|
14424
|
+
style: defaultTableProperties.borderStyle,
|
|
14425
|
+
width: defaultTableProperties.borderWidth,
|
|
14426
|
+
color: defaultTableProperties.borderColor
|
|
14427
|
+
};
|
|
14428
|
+
const colorInputCreator = getLabeledColorInputCreator({
|
|
14429
|
+
colorConfig: this.options.borderColors,
|
|
14430
|
+
columns: 5,
|
|
14431
|
+
defaultColorValue: defaultBorder.color,
|
|
14432
|
+
colorPickerConfig: this.options.colorPickerConfig
|
|
14433
|
+
});
|
|
14434
|
+
const locale = this.locale;
|
|
14435
|
+
const t = this.t;
|
|
14436
|
+
const accessibleLabel = t('Style');
|
|
14437
|
+
// -- Group label ---------------------------------------------
|
|
14438
|
+
const borderRowLabel = new LabelView(locale);
|
|
14439
|
+
borderRowLabel.text = t('Border');
|
|
14440
|
+
// -- Style ---------------------------------------------------
|
|
14441
|
+
const styleLabels = getBorderStyleLabels(t);
|
|
14442
|
+
const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
|
|
14443
|
+
borderStyleDropdown.set({
|
|
14444
|
+
label: accessibleLabel,
|
|
14445
|
+
class: 'ck-table-form__border-style'
|
|
14446
|
+
});
|
|
14447
|
+
borderStyleDropdown.fieldView.buttonView.set({
|
|
14448
|
+
ariaLabel: accessibleLabel,
|
|
14449
|
+
ariaLabelledBy: undefined,
|
|
14450
|
+
isOn: false,
|
|
14451
|
+
withText: true,
|
|
14452
|
+
tooltip: accessibleLabel
|
|
14453
|
+
});
|
|
14454
|
+
borderStyleDropdown.fieldView.buttonView.bind('label').to(this, 'borderStyle', (value)=>{
|
|
14455
|
+
return styleLabels[value ? value : 'none'];
|
|
14456
|
+
});
|
|
14457
|
+
borderStyleDropdown.fieldView.on('execute', (evt)=>{
|
|
14458
|
+
this.borderStyle = evt.source._borderStyleValue;
|
|
14459
|
+
});
|
|
14460
|
+
borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
|
|
14461
|
+
addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
|
|
14462
|
+
role: 'menu',
|
|
14463
|
+
ariaLabel: accessibleLabel
|
|
14464
|
+
});
|
|
14465
|
+
// -- Width ---------------------------------------------------
|
|
14466
|
+
const borderWidthInput = new LabeledFieldView(locale, createLabeledInputText);
|
|
14467
|
+
borderWidthInput.set({
|
|
14468
|
+
label: t('Width'),
|
|
14469
|
+
class: 'ck-table-form__border-width'
|
|
14470
|
+
});
|
|
14471
|
+
borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
|
|
14472
|
+
borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
|
|
14473
|
+
borderWidthInput.fieldView.on('input', ()=>{
|
|
14474
|
+
this.borderWidth = borderWidthInput.fieldView.element.value;
|
|
14475
|
+
});
|
|
14476
|
+
// -- Color ---------------------------------------------------
|
|
14477
|
+
const borderColorInput = new LabeledFieldView(locale, colorInputCreator);
|
|
14478
|
+
borderColorInput.set({
|
|
14479
|
+
label: t('Color'),
|
|
14480
|
+
class: 'ck-table-form__border-color'
|
|
14481
|
+
});
|
|
14482
|
+
borderColorInput.fieldView.bind('value').to(this, 'borderColor');
|
|
14483
|
+
borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet$1);
|
|
14484
|
+
borderColorInput.fieldView.on('input', ()=>{
|
|
14485
|
+
this.borderColor = borderColorInput.fieldView.value;
|
|
14486
|
+
});
|
|
14487
|
+
// Reset the border color and width fields depending on the `border-style` value.
|
|
14488
|
+
this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
|
|
14489
|
+
// When removing the border (`border-style:none`), clear the remaining `border-*` properties.
|
|
14490
|
+
// See: https://github.com/ckeditor/ckeditor5/issues/6227.
|
|
14491
|
+
if (!isBorderStyleSet$1(newValue)) {
|
|
14492
|
+
this.borderColor = '';
|
|
14493
|
+
this.borderWidth = '';
|
|
14494
|
+
}
|
|
14495
|
+
// When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
|
|
14496
|
+
if (!isBorderStyleSet$1(oldValue)) {
|
|
14497
|
+
this.borderColor = defaultBorder.color;
|
|
14498
|
+
this.borderWidth = defaultBorder.width;
|
|
14499
|
+
}
|
|
14500
|
+
});
|
|
14501
|
+
return {
|
|
14502
|
+
borderRowLabel,
|
|
14503
|
+
borderStyleDropdown,
|
|
14504
|
+
borderColorInput,
|
|
14505
|
+
borderWidthInput
|
|
14506
|
+
};
|
|
14507
|
+
}
|
|
14508
|
+
/**
|
|
14509
|
+
* Creates the following form fields:
|
|
14510
|
+
*
|
|
14511
|
+
* * {@link #backgroundInput}.
|
|
14512
|
+
*/ _createBackgroundFields() {
|
|
14513
|
+
const locale = this.locale;
|
|
14514
|
+
const t = this.t;
|
|
14515
|
+
// -- Group label ---------------------------------------------
|
|
14516
|
+
const backgroundRowLabel = new LabelView(locale);
|
|
14517
|
+
backgroundRowLabel.text = t('Background');
|
|
14518
|
+
// -- Background color input -----------------------------------
|
|
14519
|
+
const backgroundInputCreator = getLabeledColorInputCreator({
|
|
14520
|
+
colorConfig: this.options.backgroundColors,
|
|
14521
|
+
columns: 5,
|
|
14522
|
+
defaultColorValue: this.options.defaultTableProperties.backgroundColor,
|
|
14523
|
+
colorPickerConfig: this.options.colorPickerConfig
|
|
14524
|
+
});
|
|
14525
|
+
const backgroundInput = new LabeledFieldView(locale, backgroundInputCreator);
|
|
14526
|
+
backgroundInput.set({
|
|
14527
|
+
label: t('Color'),
|
|
14528
|
+
class: 'ck-table-properties-form__background'
|
|
14529
|
+
});
|
|
14530
|
+
backgroundInput.fieldView.bind('value').to(this, 'backgroundColor');
|
|
14531
|
+
backgroundInput.fieldView.on('input', ()=>{
|
|
14532
|
+
this.backgroundColor = backgroundInput.fieldView.value;
|
|
14533
|
+
});
|
|
14534
|
+
return {
|
|
14535
|
+
backgroundRowLabel,
|
|
14536
|
+
backgroundInput
|
|
14537
|
+
};
|
|
14538
|
+
}
|
|
14539
|
+
/**
|
|
14540
|
+
* Creates the following form fields:
|
|
14541
|
+
*
|
|
14542
|
+
* * {@link #widthInput},
|
|
14543
|
+
* * {@link #heightInput}.
|
|
14544
|
+
*/ _createDimensionFields() {
|
|
14545
|
+
const locale = this.locale;
|
|
14546
|
+
const t = this.t;
|
|
14547
|
+
// -- Label ---------------------------------------------------
|
|
14548
|
+
const dimensionsLabel = new LabelView(locale);
|
|
14549
|
+
dimensionsLabel.text = t('Dimensions');
|
|
14550
|
+
// -- Width ---------------------------------------------------
|
|
14551
|
+
const widthInput = new LabeledFieldView(locale, createLabeledInputText);
|
|
14552
|
+
widthInput.set({
|
|
14553
|
+
label: t('Width'),
|
|
14554
|
+
class: 'ck-table-form__dimensions-row__width'
|
|
14555
|
+
});
|
|
14556
|
+
widthInput.fieldView.bind('value').to(this, 'width');
|
|
14557
|
+
widthInput.fieldView.on('input', ()=>{
|
|
14558
|
+
this.width = widthInput.fieldView.element.value;
|
|
14559
|
+
});
|
|
14560
|
+
// -- Operator ---------------------------------------------------
|
|
14561
|
+
const operatorLabel = new View(locale);
|
|
14562
|
+
operatorLabel.setTemplate({
|
|
14563
|
+
tag: 'span',
|
|
14564
|
+
attributes: {
|
|
14565
|
+
class: [
|
|
14566
|
+
'ck-table-form__dimension-operator'
|
|
14567
|
+
]
|
|
14568
|
+
},
|
|
14569
|
+
children: [
|
|
14570
|
+
{
|
|
14571
|
+
text: '×'
|
|
14572
|
+
}
|
|
14573
|
+
]
|
|
14574
|
+
});
|
|
14575
|
+
// -- Height ---------------------------------------------------
|
|
14576
|
+
const heightInput = new LabeledFieldView(locale, createLabeledInputText);
|
|
14577
|
+
heightInput.set({
|
|
14578
|
+
label: t('Height'),
|
|
14579
|
+
class: 'ck-table-form__dimensions-row__height'
|
|
14580
|
+
});
|
|
14581
|
+
heightInput.fieldView.bind('value').to(this, 'height');
|
|
14582
|
+
heightInput.fieldView.on('input', ()=>{
|
|
14583
|
+
this.height = heightInput.fieldView.element.value;
|
|
14584
|
+
});
|
|
14585
|
+
return {
|
|
14586
|
+
dimensionsLabel,
|
|
14587
|
+
widthInput,
|
|
14588
|
+
operatorLabel,
|
|
14589
|
+
heightInput
|
|
14590
|
+
};
|
|
14591
|
+
}
|
|
14592
|
+
/**
|
|
14593
|
+
* Creates the following form fields:
|
|
14594
|
+
*
|
|
14595
|
+
* * {@link #alignmentToolbar}.
|
|
14596
|
+
*/ _createAlignmentFields() {
|
|
14597
|
+
const locale = this.locale;
|
|
14598
|
+
const t = this.t;
|
|
14599
|
+
// -- Label ---------------------------------------------------
|
|
14600
|
+
const alignmentLabel = new LabelView(locale);
|
|
14601
|
+
alignmentLabel.text = t('Table Alignment');
|
|
14602
|
+
// -- Toolbar ---------------------------------------------------
|
|
14603
|
+
const alignmentToolbar = new ToolbarView(locale);
|
|
14604
|
+
alignmentToolbar.set({
|
|
14605
|
+
role: 'radiogroup',
|
|
14606
|
+
isCompact: true,
|
|
14607
|
+
ariaLabel: t('Table alignment toolbar')
|
|
14608
|
+
});
|
|
14609
|
+
fillToolbar({
|
|
14610
|
+
view: this,
|
|
14611
|
+
icons: {
|
|
14612
|
+
left: IconObjectInlineLeft,
|
|
14613
|
+
center: IconObjectCenter,
|
|
14614
|
+
right: IconObjectInlineRight,
|
|
14615
|
+
blockLeft: IconObjectLeft,
|
|
14616
|
+
blockRight: IconObjectRight
|
|
14617
|
+
},
|
|
14618
|
+
toolbar: alignmentToolbar,
|
|
14619
|
+
labels: this._alignmentLabels,
|
|
14620
|
+
propertyName: 'alignment',
|
|
14621
|
+
defaultValue: this.options.defaultTableProperties.alignment
|
|
14622
|
+
});
|
|
14623
|
+
return {
|
|
14624
|
+
alignmentLabel,
|
|
14625
|
+
alignmentToolbar
|
|
14626
|
+
};
|
|
14627
|
+
}
|
|
14628
|
+
/**
|
|
14629
|
+
* Creates the following form controls:
|
|
14630
|
+
*
|
|
14631
|
+
* * {@link #saveButtonView},
|
|
14632
|
+
* * {@link #cancelButtonView}.
|
|
14633
|
+
*/ _createActionButtons() {
|
|
14634
|
+
const locale = this.locale;
|
|
14635
|
+
const t = this.t;
|
|
14636
|
+
const saveButtonView = new ButtonView(locale);
|
|
14637
|
+
const cancelButtonView = new ButtonView(locale);
|
|
14638
|
+
const fieldsThatShouldValidateToSave = [
|
|
14639
|
+
this.borderWidthInput,
|
|
14640
|
+
this.borderColorInput,
|
|
14641
|
+
this.backgroundInput,
|
|
14642
|
+
this.widthInput,
|
|
14643
|
+
this.heightInput
|
|
14644
|
+
];
|
|
14645
|
+
saveButtonView.set({
|
|
14646
|
+
label: t('Save'),
|
|
14647
|
+
class: 'ck-button-action',
|
|
14648
|
+
type: 'submit',
|
|
14649
|
+
withText: true
|
|
14650
|
+
});
|
|
14651
|
+
saveButtonView.bind('isEnabled').toMany(fieldsThatShouldValidateToSave, 'errorText', (...errorTexts)=>{
|
|
14652
|
+
return errorTexts.every((errorText)=>!errorText);
|
|
14653
|
+
});
|
|
14654
|
+
cancelButtonView.set({
|
|
14655
|
+
label: t('Cancel'),
|
|
14656
|
+
withText: true
|
|
14657
|
+
});
|
|
14658
|
+
cancelButtonView.delegate('execute').to(this, 'cancel');
|
|
14659
|
+
return {
|
|
14660
|
+
saveButtonView,
|
|
14661
|
+
cancelButtonView
|
|
14662
|
+
};
|
|
14663
|
+
}
|
|
14664
|
+
/**
|
|
14665
|
+
* Creates a back button view that cancels the form.
|
|
14666
|
+
*/ _createBackButton() {
|
|
14667
|
+
const t = this.locale.t;
|
|
14668
|
+
const backButton = new ButtonView(this.locale);
|
|
14669
|
+
backButton.set({
|
|
14670
|
+
class: 'ck-button-back',
|
|
14671
|
+
label: t('Back'),
|
|
14672
|
+
icon: IconPreviousArrow,
|
|
14673
|
+
tooltip: true
|
|
14674
|
+
});
|
|
14675
|
+
backButton.delegate('execute').to(this, 'cancel');
|
|
14676
|
+
return backButton;
|
|
14677
|
+
}
|
|
14678
|
+
/**
|
|
14679
|
+
* Provides localized labels for {@link #alignmentToolbar} buttons.
|
|
14680
|
+
*/ get _alignmentLabels() {
|
|
14681
|
+
const locale = this.locale;
|
|
14682
|
+
const t = this.t;
|
|
14683
|
+
const blockLeft = t('Align table to the left with no text wrapping');
|
|
14684
|
+
const blockRight = t('Align table to the right with no text wrapping');
|
|
14685
|
+
const left = t('Align table to the left with text wrapping');
|
|
14686
|
+
const center = t('Center table with no text wrapping');
|
|
14687
|
+
const right = t('Align table to the right with text wrapping');
|
|
14688
|
+
// Returns object with a proper order of labels.
|
|
14689
|
+
if (locale.uiLanguageDirection === 'rtl') {
|
|
14690
|
+
return {
|
|
14691
|
+
right,
|
|
14692
|
+
left,
|
|
14693
|
+
blockRight,
|
|
14694
|
+
center,
|
|
14695
|
+
blockLeft
|
|
14696
|
+
};
|
|
14697
|
+
}
|
|
14698
|
+
return {
|
|
14699
|
+
blockLeft,
|
|
14700
|
+
center,
|
|
14701
|
+
blockRight,
|
|
14702
|
+
left,
|
|
14703
|
+
right
|
|
14704
|
+
};
|
|
14705
|
+
}
|
|
14706
|
+
}
|
|
14707
|
+
function isBorderStyleSet$1(value) {
|
|
14708
|
+
return value !== 'none';
|
|
14709
|
+
}
|
|
14710
|
+
|
|
14711
|
+
const ERROR_TEXT_TIMEOUT$1 = 500;
|
|
14712
|
+
// Map of view properties and related commands.
|
|
14713
|
+
const propertyToCommandMap$1 = {
|
|
14714
|
+
borderStyle: 'tableBorderStyle',
|
|
14715
|
+
borderColor: 'tableBorderColor',
|
|
14716
|
+
borderWidth: 'tableBorderWidth',
|
|
14717
|
+
backgroundColor: 'tableBackgroundColor',
|
|
14718
|
+
width: 'tableWidth',
|
|
14719
|
+
height: 'tableHeight',
|
|
14720
|
+
alignment: 'tableAlignment'
|
|
14721
|
+
};
|
|
14722
|
+
/**
|
|
14723
|
+
* The table properties UI plugin. It introduces the `'tableProperties'` button
|
|
14724
|
+
* that opens a form allowing to specify visual styling of an entire table.
|
|
14725
|
+
*
|
|
14726
|
+
* It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
|
|
14727
|
+
*/ class TablePropertiesUIExperimental extends Plugin {
|
|
14728
|
+
/**
|
|
14729
|
+
* The default table properties.
|
|
14730
|
+
*/ _defaultContentTableProperties;
|
|
14731
|
+
/**
|
|
14732
|
+
* The default layout table properties.
|
|
14733
|
+
*/ _defaultLayoutTableProperties;
|
|
14734
|
+
/**
|
|
14735
|
+
* The contextual balloon plugin instance.
|
|
14736
|
+
*/ _balloon;
|
|
14737
|
+
/**
|
|
14738
|
+
* The properties form view displayed inside the balloon.
|
|
14739
|
+
*/ view = null;
|
|
14740
|
+
/**
|
|
14741
|
+
* The properties form view displayed inside the balloon (content table).
|
|
14742
|
+
*/ _viewWithContentTableDefaults = null;
|
|
14743
|
+
/**
|
|
14744
|
+
* The properties form view displayed inside the balloon (layout table).
|
|
14745
|
+
*/ _viewWithLayoutTableDefaults = null;
|
|
14746
|
+
/**
|
|
14747
|
+
* The batch used to undo all changes made by the form (which are live, as the user types)
|
|
14748
|
+
* when "Cancel" was pressed. Each time the view is shown, a new batch is created.
|
|
14749
|
+
*/ _undoStepBatch;
|
|
14750
|
+
/**
|
|
14751
|
+
* Flag used to indicate whether view is ready to execute update commands
|
|
14752
|
+
* (it finished loading initial data).
|
|
14753
|
+
*/ _isReady;
|
|
14754
|
+
/**
|
|
14755
|
+
* @inheritDoc
|
|
14756
|
+
*/ static get requires() {
|
|
14757
|
+
return [
|
|
14758
|
+
ContextualBalloon
|
|
14759
|
+
];
|
|
14760
|
+
}
|
|
14761
|
+
/**
|
|
14762
|
+
* @inheritDoc
|
|
14763
|
+
*/ static get pluginName() {
|
|
14764
|
+
return 'TablePropertiesUIExperimental';
|
|
14765
|
+
}
|
|
14766
|
+
/**
|
|
14767
|
+
* @inheritDoc
|
|
14768
|
+
*/ static get isOfficialPlugin() {
|
|
14769
|
+
return true;
|
|
14770
|
+
}
|
|
14771
|
+
/**
|
|
14772
|
+
* @inheritDoc
|
|
14773
|
+
*/ constructor(editor){
|
|
14774
|
+
super(editor);
|
|
14775
|
+
editor.config.define('table.tableProperties', {
|
|
14776
|
+
borderColors: defaultColors,
|
|
14777
|
+
backgroundColors: defaultColors
|
|
14778
|
+
});
|
|
14779
|
+
}
|
|
14780
|
+
/**
|
|
14781
|
+
* @inheritDoc
|
|
14782
|
+
*/ init() {
|
|
14783
|
+
const editor = this.editor;
|
|
14784
|
+
this._defaultContentTableProperties = getNormalizedDefaultTableProperties(editor.config.get('table.tableProperties.defaultProperties'), {
|
|
14785
|
+
includeAlignmentProperty: true
|
|
14786
|
+
});
|
|
14787
|
+
this._defaultLayoutTableProperties = getNormalizedDefaultProperties();
|
|
14788
|
+
this._balloon = editor.plugins.get(ContextualBalloon);
|
|
14789
|
+
editor.ui.componentFactory.add('tableProperties', ()=>this._createTablePropertiesButton());
|
|
14790
|
+
}
|
|
14791
|
+
/**
|
|
14792
|
+
* Creates the table properties button.
|
|
14793
|
+
*
|
|
14794
|
+
* @internal
|
|
14795
|
+
*/ _createTablePropertiesButton() {
|
|
14796
|
+
const editor = this.editor;
|
|
14797
|
+
const t = editor.t;
|
|
14798
|
+
const view = new ButtonView(editor.locale);
|
|
14799
|
+
view.set({
|
|
14800
|
+
label: t('Table properties'),
|
|
14801
|
+
icon: IconTableProperties,
|
|
14802
|
+
tooltip: true
|
|
14803
|
+
});
|
|
14804
|
+
this.listenTo(view, 'execute', ()=>this._showView());
|
|
14805
|
+
const commands = Object.values(propertyToCommandMap$1).map((commandName)=>editor.commands.get(commandName));
|
|
14806
|
+
view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
|
|
14807
|
+
return view;
|
|
14808
|
+
}
|
|
14809
|
+
/**
|
|
14810
|
+
* @inheritDoc
|
|
14811
|
+
*/ destroy() {
|
|
14812
|
+
super.destroy();
|
|
14813
|
+
// Destroy created UI components as they are not automatically destroyed.
|
|
14814
|
+
// See https://github.com/ckeditor/ckeditor5/issues/1341.
|
|
14815
|
+
if (this.view) {
|
|
14816
|
+
this.view.destroy();
|
|
14817
|
+
}
|
|
14818
|
+
}
|
|
14819
|
+
/**
|
|
14820
|
+
* Creates the {@link module:table/tableproperties/ui/tablepropertiesview~TablePropertiesView} instance.
|
|
14821
|
+
*
|
|
14822
|
+
* @returns The table properties form view instance.
|
|
14823
|
+
*/ _createPropertiesView(defaultTableProperties) {
|
|
14824
|
+
const editor = this.editor;
|
|
14825
|
+
const config = editor.config.get('table.tableProperties');
|
|
14826
|
+
const borderColorsConfig = normalizeColorOptions(config.borderColors);
|
|
14827
|
+
const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
|
|
14828
|
+
const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
|
|
14829
|
+
const localizedBackgroundColors = getLocalizedColorOptions(editor.locale, backgroundColorsConfig);
|
|
14830
|
+
const hasColorPicker = config.colorPicker !== false;
|
|
14831
|
+
const view = new TablePropertiesViewExperimental(editor.locale, {
|
|
14832
|
+
borderColors: localizedBorderColors,
|
|
14833
|
+
backgroundColors: localizedBackgroundColors,
|
|
14834
|
+
defaultTableProperties,
|
|
14835
|
+
colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false
|
|
14836
|
+
});
|
|
14837
|
+
const t = editor.t;
|
|
14838
|
+
// Render the view so its #element is available for the clickOutsideHandler.
|
|
14839
|
+
view.render();
|
|
14840
|
+
this.listenTo(view, 'submit', ()=>{
|
|
14841
|
+
this._hideView();
|
|
14842
|
+
});
|
|
14843
|
+
this.listenTo(view, 'cancel', ()=>{
|
|
14844
|
+
// https://github.com/ckeditor/ckeditor5/issues/6180
|
|
14845
|
+
if (this._undoStepBatch.operations.length) {
|
|
14846
|
+
editor.execute('undo', this._undoStepBatch);
|
|
14847
|
+
}
|
|
14848
|
+
this._hideView();
|
|
14849
|
+
});
|
|
14850
|
+
// Close the balloon on Esc key press.
|
|
14851
|
+
view.keystrokes.set('Esc', (data, cancel)=>{
|
|
14852
|
+
this._hideView();
|
|
14853
|
+
cancel();
|
|
14854
|
+
});
|
|
14855
|
+
// Close on click outside of balloon panel element.
|
|
14856
|
+
clickOutsideHandler({
|
|
14857
|
+
emitter: view,
|
|
14858
|
+
activator: ()=>this._isViewInBalloon,
|
|
14859
|
+
contextElements: [
|
|
14860
|
+
this._balloon.view.element
|
|
14861
|
+
],
|
|
14862
|
+
callback: ()=>this._hideView()
|
|
14863
|
+
});
|
|
14864
|
+
const colorErrorText = getLocalizedColorErrorText(t);
|
|
14865
|
+
const lengthErrorText = getLocalizedLengthErrorText(t);
|
|
14866
|
+
// Create the "UI -> editor data" binding.
|
|
14867
|
+
// These listeners update the editor data (via table commands) when any observable
|
|
14868
|
+
// property of the view has changed. They also validate the value and display errors in the UI
|
|
14869
|
+
// when necessary. This makes the view live, which means the changes are
|
|
14870
|
+
// visible in the editing as soon as the user types or changes fields' values.
|
|
14871
|
+
view.on('change:borderStyle', this._getPropertyChangeCallback('tableBorderStyle'));
|
|
14872
|
+
view.on('change:borderColor', this._getValidatedPropertyChangeCallback({
|
|
14873
|
+
viewField: view.borderColorInput,
|
|
14874
|
+
commandName: 'tableBorderColor',
|
|
14875
|
+
errorText: colorErrorText,
|
|
14876
|
+
validator: colorFieldValidator
|
|
14877
|
+
}));
|
|
14878
|
+
view.on('change:borderWidth', this._getValidatedPropertyChangeCallback({
|
|
14879
|
+
viewField: view.borderWidthInput,
|
|
14880
|
+
commandName: 'tableBorderWidth',
|
|
14881
|
+
errorText: lengthErrorText,
|
|
14882
|
+
validator: lineWidthFieldValidator
|
|
14883
|
+
}));
|
|
14884
|
+
view.on('change:backgroundColor', this._getValidatedPropertyChangeCallback({
|
|
14885
|
+
viewField: view.backgroundInput,
|
|
14886
|
+
commandName: 'tableBackgroundColor',
|
|
14887
|
+
errorText: colorErrorText,
|
|
14888
|
+
validator: colorFieldValidator
|
|
14889
|
+
}));
|
|
14890
|
+
view.on('change:width', this._getValidatedPropertyChangeCallback({
|
|
14891
|
+
viewField: view.widthInput,
|
|
14892
|
+
commandName: 'tableWidth',
|
|
14893
|
+
errorText: lengthErrorText,
|
|
14894
|
+
validator: lengthFieldValidator
|
|
14895
|
+
}));
|
|
14896
|
+
view.on('change:height', this._getValidatedPropertyChangeCallback({
|
|
14897
|
+
viewField: view.heightInput,
|
|
14898
|
+
commandName: 'tableHeight',
|
|
14899
|
+
errorText: lengthErrorText,
|
|
14900
|
+
validator: lengthFieldValidator
|
|
14901
|
+
}));
|
|
14902
|
+
view.on('change:alignment', this._getPropertyChangeCallback('tableAlignment'));
|
|
14903
|
+
return view;
|
|
14904
|
+
}
|
|
14905
|
+
/**
|
|
14906
|
+
* In this method the "editor data -> UI" binding is happening.
|
|
14907
|
+
*
|
|
14908
|
+
* When executed, this method obtains selected table property values from various table commands
|
|
14909
|
+
* and passes them to the {@link #view}.
|
|
14910
|
+
*
|
|
14911
|
+
* This way, the UI stays up–to–date with the editor data.
|
|
14912
|
+
*/ _fillViewFormFromCommandValues() {
|
|
14913
|
+
const commands = this.editor.commands;
|
|
14914
|
+
const borderStyleCommand = commands.get('tableBorderStyle');
|
|
14915
|
+
Object.entries(propertyToCommandMap$1).map(([property, commandName])=>{
|
|
14916
|
+
const propertyKey = property;
|
|
14917
|
+
const defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableProperties[propertyKey] || '' : this._defaultLayoutTableProperties[propertyKey] || '';
|
|
14918
|
+
return [
|
|
14919
|
+
propertyKey,
|
|
14920
|
+
commands.get(commandName).value || defaultValue
|
|
14921
|
+
];
|
|
14922
|
+
}).forEach(([property, value])=>{
|
|
14923
|
+
// Do not set the `border-color` and `border-width` fields if `border-style:none`.
|
|
14924
|
+
if ((property === 'borderColor' || property === 'borderWidth') && borderStyleCommand.value === 'none') {
|
|
14925
|
+
return;
|
|
14926
|
+
}
|
|
14927
|
+
this.view.set(property, value);
|
|
14928
|
+
});
|
|
14929
|
+
this._isReady = true;
|
|
14930
|
+
}
|
|
14931
|
+
/**
|
|
14932
|
+
* Shows the {@link #view} in the {@link #_balloon}.
|
|
14933
|
+
*
|
|
14934
|
+
* **Note**: Each time a view is shown, the new {@link #_undoStepBatch} is created that contains
|
|
14935
|
+
* all changes made to the document when the view is visible, allowing a single undo step
|
|
14936
|
+
* for all of them.
|
|
14937
|
+
*/ _showView() {
|
|
14938
|
+
const editor = this.editor;
|
|
14939
|
+
const viewTable = getSelectionAffectedTableWidget(editor.editing.view.document.selection);
|
|
14940
|
+
const modelTable = viewTable && editor.editing.mapper.toModelElement(viewTable);
|
|
14941
|
+
const useDefaults = !modelTable || modelTable.getAttribute('tableType') !== 'layout';
|
|
14942
|
+
if (useDefaults && !this._viewWithContentTableDefaults) {
|
|
14943
|
+
this._viewWithContentTableDefaults = this._createPropertiesView(this._defaultContentTableProperties);
|
|
14944
|
+
} else if (!useDefaults && !this._viewWithLayoutTableDefaults) {
|
|
14945
|
+
this._viewWithLayoutTableDefaults = this._createPropertiesView(this._defaultLayoutTableProperties);
|
|
14946
|
+
}
|
|
14947
|
+
this.view = useDefaults ? this._viewWithContentTableDefaults : this._viewWithLayoutTableDefaults;
|
|
14948
|
+
this.listenTo(editor.ui, 'update', ()=>{
|
|
14949
|
+
this._updateView();
|
|
14950
|
+
});
|
|
14951
|
+
// Update the view with the model values.
|
|
14952
|
+
this._fillViewFormFromCommandValues();
|
|
14953
|
+
this._balloon.add({
|
|
14954
|
+
view: this.view,
|
|
14955
|
+
position: getBalloonTablePositionData(editor)
|
|
14956
|
+
});
|
|
14957
|
+
// Create a new batch. Clicking "Cancel" will undo this batch.
|
|
14958
|
+
this._undoStepBatch = editor.model.createBatch();
|
|
14959
|
+
// Basic a11y.
|
|
14960
|
+
this.view.focus();
|
|
14961
|
+
}
|
|
14962
|
+
/**
|
|
14963
|
+
* Removes the {@link #view} from the {@link #_balloon}.
|
|
14964
|
+
*/ _hideView() {
|
|
14965
|
+
const editor = this.editor;
|
|
14966
|
+
this.stopListening(editor.ui, 'update');
|
|
14967
|
+
this._isReady = false;
|
|
14968
|
+
// Blur any input element before removing it from DOM to prevent issues in some browsers.
|
|
14969
|
+
// See https://github.com/ckeditor/ckeditor5/issues/1501.
|
|
14970
|
+
this.view.saveButtonView.focus();
|
|
14971
|
+
this._balloon.remove(this.view);
|
|
14972
|
+
// Make sure the focus is not lost in the process by putting it directly
|
|
14973
|
+
// into the editing view.
|
|
14974
|
+
this.editor.editing.view.focus();
|
|
14975
|
+
}
|
|
14976
|
+
/**
|
|
14977
|
+
* Repositions the {@link #_balloon} or hides the {@link #view} if a table is no longer selected.
|
|
14978
|
+
*/ _updateView() {
|
|
14979
|
+
const editor = this.editor;
|
|
14980
|
+
const viewDocument = editor.editing.view.document;
|
|
14981
|
+
if (!getSelectionAffectedTableWidget(viewDocument.selection)) {
|
|
14982
|
+
this._hideView();
|
|
14983
|
+
} else if (this._isViewVisible) {
|
|
14984
|
+
repositionContextualBalloon(editor, 'table');
|
|
14985
|
+
}
|
|
14986
|
+
}
|
|
14987
|
+
/**
|
|
14988
|
+
* Returns `true` when the {@link #view} is the visible in the {@link #_balloon}.
|
|
14989
|
+
*/ get _isViewVisible() {
|
|
14990
|
+
return !!this.view && this._balloon.visibleView === this.view;
|
|
14991
|
+
}
|
|
14992
|
+
/**
|
|
14993
|
+
* Returns `true` when the {@link #view} is in the {@link #_balloon}.
|
|
14994
|
+
*/ get _isViewInBalloon() {
|
|
14995
|
+
return !!this.view && this._balloon.hasView(this.view);
|
|
14996
|
+
}
|
|
14997
|
+
/**
|
|
14998
|
+
* Creates a callback that when executed upon {@link #view view's} property change
|
|
14999
|
+
* executes a related editor command with the new property value.
|
|
15000
|
+
*
|
|
15001
|
+
* If new value will be set to the default value, the command will not be executed.
|
|
15002
|
+
*
|
|
15003
|
+
* @param commandName The command that will be executed.
|
|
15004
|
+
*/ _getPropertyChangeCallback(commandName) {
|
|
15005
|
+
return (evt, propertyName, newValue)=>{
|
|
15006
|
+
// Do not execute the command on initial call (opening the table properties view).
|
|
15007
|
+
if (!this._isReady) {
|
|
15008
|
+
return;
|
|
15009
|
+
}
|
|
15010
|
+
this.editor.execute(commandName, {
|
|
15011
|
+
value: newValue,
|
|
15012
|
+
batch: this._undoStepBatch
|
|
15013
|
+
});
|
|
15014
|
+
};
|
|
15015
|
+
}
|
|
15016
|
+
/**
|
|
15017
|
+
* Creates a callback that when executed upon {@link #view view's} property change:
|
|
15018
|
+
* * executes a related editor command with the new property value if the value is valid,
|
|
15019
|
+
* * or sets the error text next to the invalid field, if the value did not pass the validation.
|
|
15020
|
+
*/ _getValidatedPropertyChangeCallback(options) {
|
|
15021
|
+
const { commandName, viewField, validator, errorText } = options;
|
|
15022
|
+
const setErrorTextDebounced = debounce(()=>{
|
|
15023
|
+
viewField.errorText = errorText;
|
|
15024
|
+
}, ERROR_TEXT_TIMEOUT$1);
|
|
15025
|
+
return (evt, propertyName, newValue)=>{
|
|
15026
|
+
setErrorTextDebounced.cancel();
|
|
15027
|
+
// Do not execute the command on initial call (opening the table properties view).
|
|
15028
|
+
if (!this._isReady) {
|
|
15029
|
+
return;
|
|
15030
|
+
}
|
|
15031
|
+
if (validator(newValue)) {
|
|
15032
|
+
this.editor.execute(commandName, {
|
|
15033
|
+
value: newValue,
|
|
15034
|
+
batch: this._undoStepBatch
|
|
15035
|
+
});
|
|
15036
|
+
viewField.errorText = null;
|
|
15037
|
+
} else {
|
|
15038
|
+
setErrorTextDebounced();
|
|
15039
|
+
}
|
|
15040
|
+
};
|
|
15041
|
+
}
|
|
15042
|
+
}
|
|
15043
|
+
|
|
15044
|
+
/**
|
|
15045
|
+
* The class representing a table cell properties form, allowing users to customize
|
|
15046
|
+
* certain style aspects of a table cell, for instance, border, padding, text alignment, etc..
|
|
15047
|
+
*/ class TableCellPropertiesViewExperimental extends View {
|
|
15048
|
+
/**
|
|
15049
|
+
* Options passed to the view. See {@link #constructor} to learn more.
|
|
15050
|
+
*/ options;
|
|
15051
|
+
/**
|
|
15052
|
+
* Tracks information about the DOM focus in the form.
|
|
15053
|
+
*/ focusTracker;
|
|
15054
|
+
/**
|
|
15055
|
+
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
|
15056
|
+
*/ keystrokes;
|
|
15057
|
+
/**
|
|
15058
|
+
* A collection of child views in the form.
|
|
15059
|
+
*/ children;
|
|
15060
|
+
/**
|
|
15061
|
+
* A dropdown that allows selecting the style of the table cell border.
|
|
15062
|
+
*/ borderStyleDropdown;
|
|
15063
|
+
/**
|
|
15064
|
+
* An input that allows specifying the width of the table cell border.
|
|
15065
|
+
*/ borderWidthInput;
|
|
15066
|
+
/**
|
|
15067
|
+
* An input that allows specifying the color of the table cell border.
|
|
15068
|
+
*/ borderColorInput;
|
|
15069
|
+
/**
|
|
15070
|
+
* An input that allows specifying the table cell background color.
|
|
15071
|
+
*/ backgroundInput;
|
|
15072
|
+
/**
|
|
15073
|
+
* A dropdown that allows selecting the type of the table cell (data or header).
|
|
15074
|
+
*/ cellTypeDropdown;
|
|
15075
|
+
/**
|
|
15076
|
+
* An input that allows specifying the table cell padding.
|
|
15077
|
+
*/ paddingInput;
|
|
15078
|
+
/**
|
|
15079
|
+
* An input that allows specifying the table cell width.
|
|
15080
|
+
*/ widthInput;
|
|
15081
|
+
/**
|
|
15082
|
+
* An input that allows specifying the table cell height.
|
|
15083
|
+
*/ heightInput;
|
|
15084
|
+
/**
|
|
15085
|
+
* A toolbar with buttons that allow changing the horizontal text alignment in a table cell.
|
|
15086
|
+
*/ horizontalAlignmentToolbar;
|
|
15087
|
+
/**
|
|
15088
|
+
* A toolbar with buttons that allow changing the vertical text alignment in a table cell.
|
|
15089
|
+
*/ verticalAlignmentToolbar;
|
|
15090
|
+
/**
|
|
15091
|
+
* The "Save" button view.
|
|
15092
|
+
*/ saveButtonView;
|
|
15093
|
+
/**
|
|
15094
|
+
* The "Cancel" button view.
|
|
15095
|
+
*/ cancelButtonView;
|
|
15096
|
+
/**
|
|
15097
|
+
* The "Back" button view.
|
|
15098
|
+
*/ backButtonView;
|
|
15099
|
+
/**
|
|
15100
|
+
* A collection of views that can be focused in the form.
|
|
15101
|
+
*/ _focusables;
|
|
15102
|
+
/**
|
|
15103
|
+
* Helps cycling over {@link #_focusables} in the form.
|
|
15104
|
+
*/ _focusCycler;
|
|
15105
|
+
/**
|
|
15106
|
+
* @param locale The {@link module:core/editor/editor~Editor#locale} instance.
|
|
15107
|
+
* @param options Additional configuration of the view.
|
|
15108
|
+
* @param options.borderColors A configuration of the border color palette used by the
|
|
15109
|
+
* {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#borderColorInput}.
|
|
15110
|
+
* @param options.backgroundColors A configuration of the background color palette used by the
|
|
15111
|
+
* {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#backgroundInput}.
|
|
15112
|
+
* @param options.defaultTableCellProperties The default table cell properties.
|
|
15113
|
+
* @param options.isTableCellTypeSupported A flag indicating whether the table cell type is supported.
|
|
15114
|
+
*/ constructor(locale, options){
|
|
15115
|
+
super(locale);
|
|
15116
|
+
this.set({
|
|
15117
|
+
borderStyle: '',
|
|
15118
|
+
borderWidth: '',
|
|
15119
|
+
borderColor: '',
|
|
15120
|
+
padding: '',
|
|
15121
|
+
backgroundColor: '',
|
|
15122
|
+
width: '',
|
|
15123
|
+
height: '',
|
|
15124
|
+
horizontalAlignment: '',
|
|
15125
|
+
verticalAlignment: '',
|
|
15126
|
+
cellType: ''
|
|
15127
|
+
});
|
|
15128
|
+
this.options = options;
|
|
15129
|
+
const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
|
|
15130
|
+
const { backgroundRowLabel, backgroundInput } = this._createBackgroundFields();
|
|
15131
|
+
const { cellTypeRowLabel, cellTypeDropdown } = this._createCellTypeField();
|
|
15132
|
+
const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
|
|
15133
|
+
const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
|
|
15134
|
+
this.focusTracker = new FocusTracker();
|
|
15135
|
+
this.keystrokes = new KeystrokeHandler();
|
|
15136
|
+
this.children = this.createCollection();
|
|
15137
|
+
this.borderStyleDropdown = borderStyleDropdown;
|
|
15138
|
+
this.borderWidthInput = borderWidthInput;
|
|
15139
|
+
this.borderColorInput = borderColorInput;
|
|
15140
|
+
this.backgroundInput = backgroundInput;
|
|
15141
|
+
this.cellTypeDropdown = cellTypeDropdown;
|
|
15142
|
+
this.paddingInput = this._createPaddingField();
|
|
15143
|
+
this.widthInput = widthInput;
|
|
15144
|
+
this.heightInput = heightInput;
|
|
15145
|
+
this.horizontalAlignmentToolbar = horizontalAlignmentToolbar;
|
|
15146
|
+
this.verticalAlignmentToolbar = verticalAlignmentToolbar;
|
|
15147
|
+
// Defer creating to make sure other fields are present and the Save button can
|
|
15148
|
+
// bind its #isEnabled to their error messages so there's no way to save unless all
|
|
15149
|
+
// fields are valid.
|
|
15150
|
+
const { saveButtonView, cancelButtonView } = this._createActionButtons();
|
|
15151
|
+
this.saveButtonView = saveButtonView;
|
|
15152
|
+
this.cancelButtonView = cancelButtonView;
|
|
15153
|
+
this.backButtonView = this._createBackButton();
|
|
15154
|
+
this._focusables = new ViewCollection();
|
|
15155
|
+
this._focusCycler = new FocusCycler({
|
|
15156
|
+
focusables: this._focusables,
|
|
15157
|
+
focusTracker: this.focusTracker,
|
|
15158
|
+
keystrokeHandler: this.keystrokes,
|
|
15159
|
+
actions: {
|
|
15160
|
+
// Navigate form fields backwards using the Shift + Tab keystroke.
|
|
15161
|
+
focusPrevious: 'shift + tab',
|
|
15162
|
+
// Navigate form fields forwards using the Tab key.
|
|
15163
|
+
focusNext: 'tab'
|
|
15164
|
+
}
|
|
15165
|
+
});
|
|
15166
|
+
// Form header.
|
|
15167
|
+
const header = new FormHeaderView(locale, {
|
|
15168
|
+
label: this.t('Cell properties')
|
|
15169
|
+
});
|
|
15170
|
+
header.children.add(this.backButtonView, 0);
|
|
15171
|
+
this.children.add(header);
|
|
15172
|
+
// Border row.
|
|
15173
|
+
this.children.add(new FormRowView(locale, {
|
|
15174
|
+
labelView: borderRowLabel,
|
|
15175
|
+
children: this.options.isTableCellTypeSupported ? [
|
|
15176
|
+
borderRowLabel,
|
|
15177
|
+
borderStyleDropdown,
|
|
15178
|
+
borderWidthInput,
|
|
15179
|
+
borderColorInput
|
|
15180
|
+
] : [
|
|
15181
|
+
borderRowLabel,
|
|
15182
|
+
borderStyleDropdown,
|
|
15183
|
+
borderColorInput,
|
|
15184
|
+
borderWidthInput
|
|
15185
|
+
],
|
|
15186
|
+
class: `ck-table-form__border-row${this.options.isTableCellTypeSupported ? ' ck-table-form__border-row_experimental' : ''}`
|
|
15187
|
+
}));
|
|
15188
|
+
// Background and cell type.
|
|
15189
|
+
this.children.add(new FormRowView(locale, {
|
|
15190
|
+
children: this.options.isTableCellTypeSupported ? [
|
|
15191
|
+
new FormRowView(locale, {
|
|
15192
|
+
labelView: cellTypeRowLabel,
|
|
15193
|
+
children: [
|
|
15194
|
+
cellTypeRowLabel,
|
|
15195
|
+
cellTypeDropdown
|
|
15196
|
+
],
|
|
15197
|
+
class: 'ck-table-form__cell-type-row'
|
|
15198
|
+
}),
|
|
15199
|
+
new FormRowView(locale, {
|
|
15200
|
+
labelView: backgroundRowLabel,
|
|
15201
|
+
children: [
|
|
15202
|
+
backgroundRowLabel,
|
|
15203
|
+
backgroundInput
|
|
15204
|
+
],
|
|
15205
|
+
class: 'ck-table-form__background-row'
|
|
15206
|
+
})
|
|
15207
|
+
] : [
|
|
15208
|
+
new FormRowView(locale, {
|
|
15209
|
+
labelView: backgroundRowLabel,
|
|
15210
|
+
children: [
|
|
15211
|
+
backgroundRowLabel,
|
|
15212
|
+
backgroundInput
|
|
15213
|
+
],
|
|
15214
|
+
class: 'ck-table-form__background-row'
|
|
15215
|
+
})
|
|
15216
|
+
]
|
|
15217
|
+
}));
|
|
15218
|
+
// Dimensions row and padding.
|
|
15219
|
+
this.children.add(new FormRowView(locale, {
|
|
15220
|
+
children: [
|
|
15221
|
+
// Dimensions row.
|
|
15222
|
+
new FormRowView(locale, {
|
|
15223
|
+
labelView: dimensionsLabel,
|
|
15224
|
+
children: [
|
|
15225
|
+
dimensionsLabel,
|
|
15226
|
+
widthInput,
|
|
15227
|
+
operatorLabel,
|
|
15228
|
+
heightInput
|
|
15229
|
+
],
|
|
15230
|
+
class: 'ck-table-form__dimensions-row'
|
|
15231
|
+
}),
|
|
15232
|
+
// Padding row.
|
|
15233
|
+
new FormRowView(locale, {
|
|
15234
|
+
children: [
|
|
15235
|
+
this.paddingInput
|
|
15236
|
+
],
|
|
15237
|
+
class: 'ck-table-cell-properties-form__padding-row'
|
|
15238
|
+
})
|
|
15239
|
+
]
|
|
15240
|
+
}));
|
|
15241
|
+
// Text alignment row.
|
|
15242
|
+
this.children.add(new FormRowView(locale, {
|
|
15243
|
+
labelView: alignmentLabel,
|
|
15244
|
+
children: [
|
|
15245
|
+
alignmentLabel,
|
|
15246
|
+
horizontalAlignmentToolbar,
|
|
15247
|
+
verticalAlignmentToolbar
|
|
15248
|
+
],
|
|
15249
|
+
class: 'ck-table-cell-properties-form__alignment-row'
|
|
15250
|
+
}));
|
|
15251
|
+
// Action row.
|
|
15252
|
+
this.children.add(new FormRowView(locale, {
|
|
15253
|
+
children: [
|
|
15254
|
+
this.cancelButtonView,
|
|
15255
|
+
this.saveButtonView
|
|
15256
|
+
],
|
|
15257
|
+
class: 'ck-table-form__action-row'
|
|
15258
|
+
}));
|
|
15259
|
+
this.setTemplate({
|
|
15260
|
+
tag: 'form',
|
|
15261
|
+
attributes: {
|
|
15262
|
+
class: [
|
|
15263
|
+
'ck',
|
|
15264
|
+
'ck-form',
|
|
15265
|
+
'ck-table-form',
|
|
15266
|
+
'ck-table-cell-properties-form',
|
|
15267
|
+
'ck-table-cell-properties-form_experimental',
|
|
15268
|
+
this.options.isTableCellTypeSupported ? 'ck-table-cell-properties-form_experimental-no-cell-type' : ''
|
|
15269
|
+
],
|
|
15270
|
+
// https://github.com/ckeditor/ckeditor5-link/issues/90
|
|
15271
|
+
tabindex: '-1'
|
|
15272
|
+
},
|
|
15273
|
+
children: this.children
|
|
15274
|
+
});
|
|
15275
|
+
}
|
|
15276
|
+
/**
|
|
15277
|
+
* @inheritDoc
|
|
15278
|
+
*/ render() {
|
|
15279
|
+
super.render();
|
|
15280
|
+
// Enable the "submit" event for this view. It can be triggered by the #saveButtonView
|
|
15281
|
+
// which is of the "submit" DOM "type".
|
|
15282
|
+
submitHandler({
|
|
15283
|
+
view: this
|
|
15284
|
+
});
|
|
15285
|
+
// Maintain continuous focus cycling over views that have focusable children and focus cyclers themselves.
|
|
15286
|
+
[
|
|
15287
|
+
this.borderColorInput,
|
|
15288
|
+
this.backgroundInput
|
|
15289
|
+
].forEach((view)=>{
|
|
15290
|
+
this._focusCycler.chain(view.fieldView.focusCycler);
|
|
15291
|
+
});
|
|
15292
|
+
[
|
|
15293
|
+
this.borderStyleDropdown,
|
|
15294
|
+
this.borderColorInput,
|
|
15295
|
+
this.borderWidthInput,
|
|
15296
|
+
this.cellTypeDropdown,
|
|
15297
|
+
this.backgroundInput,
|
|
15298
|
+
this.widthInput,
|
|
15299
|
+
this.heightInput,
|
|
15300
|
+
this.paddingInput,
|
|
15301
|
+
this.horizontalAlignmentToolbar,
|
|
15302
|
+
this.verticalAlignmentToolbar,
|
|
15303
|
+
this.cancelButtonView,
|
|
15304
|
+
this.saveButtonView,
|
|
15305
|
+
this.backButtonView
|
|
15306
|
+
].forEach((view)=>{
|
|
15307
|
+
// Register the view as focusable.
|
|
15308
|
+
this._focusables.add(view);
|
|
15309
|
+
// Register the view in the focus tracker.
|
|
15310
|
+
this.focusTracker.add(view.element);
|
|
15311
|
+
});
|
|
15312
|
+
// Mainly for closing using "Esc" and navigation using "Tab".
|
|
15313
|
+
this.keystrokes.listenTo(this.element);
|
|
15314
|
+
}
|
|
15315
|
+
/**
|
|
15316
|
+
* @inheritDoc
|
|
15317
|
+
*/ destroy() {
|
|
15318
|
+
super.destroy();
|
|
15319
|
+
this.focusTracker.destroy();
|
|
15320
|
+
this.keystrokes.destroy();
|
|
15321
|
+
}
|
|
15322
|
+
/**
|
|
15323
|
+
* Focuses the fist focusable field in the form.
|
|
15324
|
+
*/ focus() {
|
|
15325
|
+
this._focusCycler.focusFirst();
|
|
15326
|
+
}
|
|
15327
|
+
/**
|
|
15328
|
+
* Creates the following form fields:
|
|
15329
|
+
*
|
|
15330
|
+
* * {@link #borderStyleDropdown},
|
|
15331
|
+
* * {@link #borderWidthInput},
|
|
15332
|
+
* * {@link #borderColorInput}.
|
|
15333
|
+
*/ _createBorderFields() {
|
|
15334
|
+
const defaultTableCellProperties = this.options.defaultTableCellProperties;
|
|
15335
|
+
const defaultBorder = {
|
|
15336
|
+
style: defaultTableCellProperties.borderStyle,
|
|
15337
|
+
width: defaultTableCellProperties.borderWidth,
|
|
15338
|
+
color: defaultTableCellProperties.borderColor
|
|
15339
|
+
};
|
|
15340
|
+
const colorInputCreator = getLabeledColorInputCreator({
|
|
15341
|
+
colorConfig: this.options.borderColors,
|
|
15342
|
+
columns: 5,
|
|
15343
|
+
defaultColorValue: defaultBorder.color,
|
|
15344
|
+
colorPickerConfig: this.options.colorPickerConfig
|
|
15345
|
+
});
|
|
15346
|
+
const locale = this.locale;
|
|
15347
|
+
const t = this.t;
|
|
15348
|
+
const accessibleLabel = t('Style');
|
|
15349
|
+
// -- Group label ---------------------------------------------
|
|
15350
|
+
const borderRowLabel = new LabelView(locale);
|
|
15351
|
+
borderRowLabel.text = t('Border');
|
|
15352
|
+
// -- Style ---------------------------------------------------
|
|
15353
|
+
const styleLabels = getBorderStyleLabels(t);
|
|
15354
|
+
const borderStyleDropdown = new LabeledFieldView(locale, createLabeledDropdown);
|
|
15355
|
+
borderStyleDropdown.set({
|
|
15356
|
+
label: accessibleLabel,
|
|
15357
|
+
class: 'ck-table-form__border-style'
|
|
15358
|
+
});
|
|
15359
|
+
borderStyleDropdown.fieldView.buttonView.set({
|
|
15360
|
+
ariaLabel: accessibleLabel,
|
|
15361
|
+
ariaLabelledBy: undefined,
|
|
15362
|
+
isOn: false,
|
|
15363
|
+
withText: true,
|
|
15364
|
+
tooltip: accessibleLabel
|
|
15365
|
+
});
|
|
15366
|
+
borderStyleDropdown.fieldView.buttonView.bind('label').to(this, 'borderStyle', (value)=>{
|
|
15367
|
+
return styleLabels[value ? value : 'none'];
|
|
15368
|
+
});
|
|
15369
|
+
borderStyleDropdown.fieldView.on('execute', (evt)=>{
|
|
15370
|
+
this.borderStyle = evt.source._borderStyleValue;
|
|
15371
|
+
});
|
|
15372
|
+
borderStyleDropdown.bind('isEmpty').to(this, 'borderStyle', (value)=>!value);
|
|
15373
|
+
addListToDropdown(borderStyleDropdown.fieldView, getBorderStyleDefinitions(this, defaultBorder.style), {
|
|
15374
|
+
role: 'menu',
|
|
15375
|
+
ariaLabel: accessibleLabel
|
|
15376
|
+
});
|
|
15377
|
+
// -- Width ---------------------------------------------------
|
|
15378
|
+
const borderWidthInput = new LabeledFieldView(locale, createLabeledInputText);
|
|
15379
|
+
borderWidthInput.set({
|
|
15380
|
+
label: t('Width'),
|
|
15381
|
+
class: 'ck-table-form__border-width'
|
|
15382
|
+
});
|
|
15383
|
+
borderWidthInput.fieldView.bind('value').to(this, 'borderWidth');
|
|
15384
|
+
borderWidthInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
|
|
15385
|
+
borderWidthInput.fieldView.on('input', ()=>{
|
|
15386
|
+
this.borderWidth = borderWidthInput.fieldView.element.value;
|
|
15387
|
+
});
|
|
15388
|
+
// -- Color ---------------------------------------------------
|
|
15389
|
+
const borderColorInput = new LabeledFieldView(locale, colorInputCreator);
|
|
15390
|
+
borderColorInput.set({
|
|
15391
|
+
label: t('Color'),
|
|
15392
|
+
class: 'ck-table-form__border-color'
|
|
15393
|
+
});
|
|
15394
|
+
borderColorInput.fieldView.bind('value').to(this, 'borderColor');
|
|
15395
|
+
borderColorInput.bind('isEnabled').to(this, 'borderStyle', isBorderStyleSet);
|
|
15396
|
+
borderColorInput.fieldView.on('input', ()=>{
|
|
15397
|
+
this.borderColor = borderColorInput.fieldView.value;
|
|
15398
|
+
});
|
|
15399
|
+
// Reset the border color and width fields depending on the `border-style` value.
|
|
15400
|
+
this.on('change:borderStyle', (evt, name, newValue, oldValue)=>{
|
|
15401
|
+
// When removing the border (`border-style:none`), clear the remaining `border-*` properties.
|
|
15402
|
+
// See: https://github.com/ckeditor/ckeditor5/issues/6227.
|
|
15403
|
+
if (!isBorderStyleSet(newValue)) {
|
|
15404
|
+
this.borderColor = '';
|
|
15405
|
+
this.borderWidth = '';
|
|
15406
|
+
}
|
|
15407
|
+
// When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties.
|
|
15408
|
+
if (!isBorderStyleSet(oldValue)) {
|
|
15409
|
+
this.borderColor = defaultBorder.color;
|
|
15410
|
+
this.borderWidth = defaultBorder.width;
|
|
15411
|
+
}
|
|
15412
|
+
});
|
|
15413
|
+
return {
|
|
15414
|
+
borderRowLabel,
|
|
15415
|
+
borderStyleDropdown,
|
|
15416
|
+
borderColorInput,
|
|
15417
|
+
borderWidthInput
|
|
15418
|
+
};
|
|
15419
|
+
}
|
|
15420
|
+
/**
|
|
15421
|
+
* Creates the following form fields:
|
|
15422
|
+
*
|
|
15423
|
+
* * {@link #backgroundInput}.
|
|
15424
|
+
*/ _createBackgroundFields() {
|
|
15425
|
+
const locale = this.locale;
|
|
15426
|
+
const t = this.t;
|
|
15427
|
+
// -- Group label ---------------------------------------------
|
|
15428
|
+
const backgroundRowLabel = new LabelView(locale);
|
|
15429
|
+
backgroundRowLabel.text = t('Background');
|
|
15430
|
+
// -- Background color input -----------------------------------
|
|
15431
|
+
const colorInputCreator = getLabeledColorInputCreator({
|
|
15432
|
+
colorConfig: this.options.backgroundColors,
|
|
15433
|
+
columns: 5,
|
|
15434
|
+
defaultColorValue: this.options.defaultTableCellProperties.backgroundColor,
|
|
15435
|
+
colorPickerConfig: this.options.colorPickerConfig
|
|
15436
|
+
});
|
|
15437
|
+
const backgroundInput = new LabeledFieldView(locale, colorInputCreator);
|
|
15438
|
+
backgroundInput.set({
|
|
15439
|
+
label: t('Color'),
|
|
15440
|
+
class: 'ck-table-cell-properties-form__background'
|
|
15441
|
+
});
|
|
15442
|
+
backgroundInput.fieldView.bind('value').to(this, 'backgroundColor');
|
|
15443
|
+
backgroundInput.fieldView.on('input', ()=>{
|
|
15444
|
+
this.backgroundColor = backgroundInput.fieldView.value;
|
|
15445
|
+
});
|
|
15446
|
+
return {
|
|
15447
|
+
backgroundRowLabel,
|
|
15448
|
+
backgroundInput
|
|
15449
|
+
};
|
|
15450
|
+
}
|
|
15451
|
+
/**
|
|
15452
|
+
* Create cell type field.
|
|
15453
|
+
*
|
|
15454
|
+
* * {@link #cellTypeDropdown}.
|
|
15455
|
+
*
|
|
15456
|
+
* @internal
|
|
15457
|
+
*/ _createCellTypeField() {
|
|
15458
|
+
const locale = this.locale;
|
|
15459
|
+
const t = this.t;
|
|
15460
|
+
const cellTypeRowLabel = new LabelView(locale);
|
|
15461
|
+
cellTypeRowLabel.text = t('Cell type');
|
|
15462
|
+
const cellTypeLabels = this._cellTypeLabels;
|
|
15463
|
+
const cellTypeDropdown = new LabeledFieldView(locale, createLabeledDropdown);
|
|
15464
|
+
cellTypeDropdown.set({
|
|
15465
|
+
label: t('Cell type'),
|
|
15466
|
+
class: 'ck-table-cell-properties-form__cell-type'
|
|
15467
|
+
});
|
|
15468
|
+
cellTypeDropdown.fieldView.buttonView.set({
|
|
15469
|
+
ariaLabel: t('Cell type'),
|
|
15470
|
+
ariaLabelledBy: undefined,
|
|
15471
|
+
isOn: false,
|
|
15472
|
+
withText: true,
|
|
15473
|
+
tooltip: t('Cell type')
|
|
15474
|
+
});
|
|
15475
|
+
cellTypeDropdown.fieldView.buttonView.bind('label').to(this, 'cellType', (value)=>{
|
|
15476
|
+
return cellTypeLabels[value || 'data'];
|
|
15477
|
+
});
|
|
15478
|
+
cellTypeDropdown.fieldView.on('execute', (evt)=>{
|
|
15479
|
+
this.cellType = evt.source._cellTypeValue;
|
|
15480
|
+
});
|
|
15481
|
+
cellTypeDropdown.bind('isEmpty').to(this, 'cellType', (value)=>!value);
|
|
15482
|
+
addListToDropdown(cellTypeDropdown.fieldView, this._getCellTypeDefinitions(), {
|
|
15483
|
+
role: 'menu',
|
|
15484
|
+
ariaLabel: t('Cell type')
|
|
15485
|
+
});
|
|
15486
|
+
return {
|
|
15487
|
+
cellTypeRowLabel,
|
|
15488
|
+
cellTypeDropdown
|
|
15489
|
+
};
|
|
15490
|
+
}
|
|
15491
|
+
/**
|
|
15492
|
+
* Creates the following form fields:
|
|
15493
|
+
*
|
|
15494
|
+
* * {@link #widthInput}.
|
|
15495
|
+
* * {@link #heightInput}.
|
|
15496
|
+
*/ _createDimensionFields() {
|
|
15497
|
+
const locale = this.locale;
|
|
15498
|
+
const t = this.t;
|
|
15499
|
+
// -- Label ---------------------------------------------------
|
|
15500
|
+
const dimensionsLabel = new LabelView(locale);
|
|
15501
|
+
dimensionsLabel.text = t('Dimensions');
|
|
15502
|
+
// -- Width ---------------------------------------------------
|
|
15503
|
+
const widthInput = new LabeledFieldView(locale, createLabeledInputText);
|
|
15504
|
+
widthInput.set({
|
|
15505
|
+
label: t('Width'),
|
|
15506
|
+
class: 'ck-table-form__dimensions-row__width'
|
|
15507
|
+
});
|
|
15508
|
+
widthInput.fieldView.bind('value').to(this, 'width');
|
|
15509
|
+
widthInput.fieldView.on('input', ()=>{
|
|
15510
|
+
this.width = widthInput.fieldView.element.value;
|
|
15511
|
+
});
|
|
15512
|
+
// -- Operator ---------------------------------------------------
|
|
15513
|
+
const operatorLabel = new View(locale);
|
|
15514
|
+
operatorLabel.setTemplate({
|
|
15515
|
+
tag: 'span',
|
|
15516
|
+
attributes: {
|
|
15517
|
+
class: [
|
|
15518
|
+
'ck-table-form__dimension-operator'
|
|
15519
|
+
]
|
|
15520
|
+
},
|
|
15521
|
+
children: [
|
|
15522
|
+
{
|
|
15523
|
+
text: '×'
|
|
15524
|
+
}
|
|
15525
|
+
]
|
|
15526
|
+
});
|
|
15527
|
+
// -- Height ---------------------------------------------------
|
|
15528
|
+
const heightInput = new LabeledFieldView(locale, createLabeledInputText);
|
|
15529
|
+
heightInput.set({
|
|
15530
|
+
label: t('Height'),
|
|
15531
|
+
class: 'ck-table-form__dimensions-row__height'
|
|
15532
|
+
});
|
|
15533
|
+
heightInput.fieldView.bind('value').to(this, 'height');
|
|
15534
|
+
heightInput.fieldView.on('input', ()=>{
|
|
15535
|
+
this.height = heightInput.fieldView.element.value;
|
|
15536
|
+
});
|
|
15537
|
+
return {
|
|
15538
|
+
dimensionsLabel,
|
|
15539
|
+
widthInput,
|
|
15540
|
+
operatorLabel,
|
|
15541
|
+
heightInput
|
|
15542
|
+
};
|
|
15543
|
+
}
|
|
15544
|
+
/**
|
|
15545
|
+
* Creates the following form fields:
|
|
15546
|
+
*
|
|
15547
|
+
* * {@link #paddingInput}.
|
|
15548
|
+
*/ _createPaddingField() {
|
|
15549
|
+
const locale = this.locale;
|
|
15550
|
+
const t = this.t;
|
|
15551
|
+
const paddingInput = new LabeledFieldView(locale, createLabeledInputText);
|
|
15552
|
+
paddingInput.set({
|
|
15553
|
+
label: t('Padding'),
|
|
15554
|
+
class: 'ck-table-cell-properties-form__padding'
|
|
15555
|
+
});
|
|
15556
|
+
paddingInput.fieldView.bind('value').to(this, 'padding');
|
|
15557
|
+
paddingInput.fieldView.on('input', ()=>{
|
|
15558
|
+
this.padding = paddingInput.fieldView.element.value;
|
|
15559
|
+
});
|
|
15560
|
+
return paddingInput;
|
|
15561
|
+
}
|
|
15562
|
+
/**
|
|
15563
|
+
* Creates the following form fields:
|
|
15564
|
+
*
|
|
15565
|
+
* * {@link #horizontalAlignmentToolbar},
|
|
15566
|
+
* * {@link #verticalAlignmentToolbar}.
|
|
15567
|
+
*/ _createAlignmentFields() {
|
|
15568
|
+
const locale = this.locale;
|
|
15569
|
+
const t = this.t;
|
|
15570
|
+
const alignmentLabel = new LabelView(locale);
|
|
15571
|
+
const ALIGNMENT_ICONS = {
|
|
15572
|
+
left: IconAlignLeft,
|
|
15573
|
+
center: IconAlignCenter,
|
|
15574
|
+
right: IconAlignRight,
|
|
15575
|
+
justify: IconAlignJustify,
|
|
15576
|
+
top: IconAlignTop,
|
|
15577
|
+
middle: IconAlignMiddle,
|
|
15578
|
+
bottom: IconAlignBottom
|
|
15579
|
+
};
|
|
15580
|
+
alignmentLabel.text = t('Table cell text alignment');
|
|
15581
|
+
// -- Horizontal ---------------------------------------------------
|
|
15582
|
+
const horizontalAlignmentToolbar = new ToolbarView(locale);
|
|
15583
|
+
const isContentRTL = locale.contentLanguageDirection === 'rtl';
|
|
15584
|
+
horizontalAlignmentToolbar.set({
|
|
15585
|
+
isCompact: true,
|
|
15586
|
+
role: 'radiogroup',
|
|
15587
|
+
ariaLabel: t('Horizontal text alignment toolbar'),
|
|
15588
|
+
class: 'ck-table-cell-properties-form__horizontal-alignment-toolbar'
|
|
15589
|
+
});
|
|
15590
|
+
fillToolbar({
|
|
15591
|
+
view: this,
|
|
15592
|
+
icons: ALIGNMENT_ICONS,
|
|
15593
|
+
toolbar: horizontalAlignmentToolbar,
|
|
15594
|
+
labels: this._horizontalAlignmentLabels,
|
|
15595
|
+
propertyName: 'horizontalAlignment',
|
|
15596
|
+
nameToValue: (name)=>{
|
|
15597
|
+
// For the RTL content, we want to swap the buttons "align to the left" and "align to the right".
|
|
15598
|
+
if (isContentRTL) {
|
|
15599
|
+
if (name === 'left') {
|
|
15600
|
+
return 'right';
|
|
15601
|
+
} else if (name === 'right') {
|
|
15602
|
+
return 'left';
|
|
15603
|
+
}
|
|
15604
|
+
}
|
|
15605
|
+
return name;
|
|
15606
|
+
},
|
|
15607
|
+
defaultValue: this.options.defaultTableCellProperties.horizontalAlignment
|
|
15608
|
+
});
|
|
15609
|
+
// -- Vertical -----------------------------------------------------
|
|
15610
|
+
const verticalAlignmentToolbar = new ToolbarView(locale);
|
|
15611
|
+
verticalAlignmentToolbar.set({
|
|
15612
|
+
isCompact: true,
|
|
15613
|
+
role: 'radiogroup',
|
|
15614
|
+
ariaLabel: t('Vertical text alignment toolbar'),
|
|
15615
|
+
class: 'ck-table-cell-properties-form__vertical-alignment-toolbar'
|
|
15616
|
+
});
|
|
15617
|
+
fillToolbar({
|
|
15618
|
+
view: this,
|
|
15619
|
+
icons: ALIGNMENT_ICONS,
|
|
15620
|
+
toolbar: verticalAlignmentToolbar,
|
|
15621
|
+
labels: this._verticalAlignmentLabels,
|
|
15622
|
+
propertyName: 'verticalAlignment',
|
|
15623
|
+
defaultValue: this.options.defaultTableCellProperties.verticalAlignment
|
|
15624
|
+
});
|
|
15625
|
+
return {
|
|
15626
|
+
horizontalAlignmentToolbar,
|
|
15627
|
+
verticalAlignmentToolbar,
|
|
15628
|
+
alignmentLabel
|
|
15629
|
+
};
|
|
15630
|
+
}
|
|
15631
|
+
/**
|
|
15632
|
+
* Creates the following form controls:
|
|
15633
|
+
*
|
|
15634
|
+
* * {@link #saveButtonView},
|
|
15635
|
+
* * {@link #cancelButtonView}.
|
|
15636
|
+
*/ _createActionButtons() {
|
|
15637
|
+
const locale = this.locale;
|
|
15638
|
+
const t = this.t;
|
|
15639
|
+
const saveButtonView = new ButtonView(locale);
|
|
15640
|
+
const cancelButtonView = new ButtonView(locale);
|
|
15641
|
+
const fieldsThatShouldValidateToSave = [
|
|
15642
|
+
this.borderWidthInput,
|
|
15643
|
+
this.borderColorInput,
|
|
15644
|
+
this.backgroundInput,
|
|
15645
|
+
this.paddingInput
|
|
15646
|
+
];
|
|
15647
|
+
saveButtonView.set({
|
|
15648
|
+
label: t('Save'),
|
|
15649
|
+
class: 'ck-button-action',
|
|
15650
|
+
type: 'submit',
|
|
15651
|
+
withText: true
|
|
15652
|
+
});
|
|
15653
|
+
saveButtonView.bind('isEnabled').toMany(fieldsThatShouldValidateToSave, 'errorText', (...errorTexts)=>{
|
|
15654
|
+
return errorTexts.every((errorText)=>!errorText);
|
|
15655
|
+
});
|
|
15656
|
+
cancelButtonView.set({
|
|
15657
|
+
label: t('Cancel'),
|
|
15658
|
+
withText: true
|
|
15659
|
+
});
|
|
15660
|
+
cancelButtonView.delegate('execute').to(this, 'cancel');
|
|
15661
|
+
return {
|
|
15662
|
+
saveButtonView,
|
|
15663
|
+
cancelButtonView
|
|
15664
|
+
};
|
|
15665
|
+
}
|
|
15666
|
+
/**
|
|
15667
|
+
* Creates a back button view that cancels the form.
|
|
15668
|
+
*/ _createBackButton() {
|
|
15669
|
+
const t = this.locale.t;
|
|
15670
|
+
const backButton = new ButtonView(this.locale);
|
|
15671
|
+
backButton.set({
|
|
15672
|
+
class: 'ck-button-back',
|
|
15673
|
+
label: t('Back'),
|
|
15674
|
+
icon: IconPreviousArrow,
|
|
15675
|
+
tooltip: true
|
|
15676
|
+
});
|
|
15677
|
+
backButton.delegate('execute').to(this, 'cancel');
|
|
15678
|
+
return backButton;
|
|
15679
|
+
}
|
|
15680
|
+
/**
|
|
15681
|
+
* Creates the cell type dropdown definitions.
|
|
15682
|
+
*/ _getCellTypeDefinitions() {
|
|
15683
|
+
const itemDefinitions = new Collection();
|
|
15684
|
+
const cellTypeLabels = this._cellTypeLabels;
|
|
15685
|
+
for (const type of [
|
|
15686
|
+
'data',
|
|
15687
|
+
'header'
|
|
15688
|
+
]){
|
|
15689
|
+
const definition = {
|
|
15690
|
+
type: 'button',
|
|
15691
|
+
model: new UIModel({
|
|
15692
|
+
_cellTypeValue: type,
|
|
15693
|
+
label: cellTypeLabels[type],
|
|
15694
|
+
role: 'menuitemradio',
|
|
15695
|
+
withText: true
|
|
15696
|
+
})
|
|
15697
|
+
};
|
|
15698
|
+
definition.model.bind('isOn').to(this, 'cellType', (value)=>value === type);
|
|
15699
|
+
itemDefinitions.add(definition);
|
|
15700
|
+
}
|
|
15701
|
+
return itemDefinitions;
|
|
15702
|
+
}
|
|
15703
|
+
/**
|
|
15704
|
+
* Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
|
|
15705
|
+
*/ get _horizontalAlignmentLabels() {
|
|
15706
|
+
const locale = this.locale;
|
|
15707
|
+
const t = this.t;
|
|
15708
|
+
const left = t('Align cell text to the left');
|
|
15709
|
+
const center = t('Align cell text to the center');
|
|
15710
|
+
const right = t('Align cell text to the right');
|
|
15711
|
+
const justify = t('Justify cell text');
|
|
15712
|
+
// Returns object with a proper order of labels.
|
|
15713
|
+
if (locale.uiLanguageDirection === 'rtl') {
|
|
15714
|
+
return {
|
|
15715
|
+
right,
|
|
15716
|
+
center,
|
|
15717
|
+
left,
|
|
15718
|
+
justify
|
|
15719
|
+
};
|
|
15720
|
+
} else {
|
|
15721
|
+
return {
|
|
15722
|
+
left,
|
|
15723
|
+
center,
|
|
15724
|
+
right,
|
|
15725
|
+
justify
|
|
15726
|
+
};
|
|
15727
|
+
}
|
|
15728
|
+
}
|
|
15729
|
+
/**
|
|
15730
|
+
* Provides localized labels for {@link #verticalAlignmentToolbar} buttons.
|
|
15731
|
+
*/ get _verticalAlignmentLabels() {
|
|
15732
|
+
const t = this.t;
|
|
15733
|
+
return {
|
|
15734
|
+
top: t('Align cell text to the top'),
|
|
15735
|
+
middle: t('Align cell text to the middle'),
|
|
15736
|
+
bottom: t('Align cell text to the bottom')
|
|
15737
|
+
};
|
|
15738
|
+
}
|
|
15739
|
+
/**
|
|
15740
|
+
* Provides localized labels for {@link #cellTypeDropdown}.
|
|
15741
|
+
*/ get _cellTypeLabels() {
|
|
15742
|
+
const t = this.t;
|
|
15743
|
+
return {
|
|
15744
|
+
data: t('Data cell'),
|
|
15745
|
+
header: t('Header cell')
|
|
15746
|
+
};
|
|
15747
|
+
}
|
|
15748
|
+
}
|
|
15749
|
+
function isBorderStyleSet(value) {
|
|
15750
|
+
return value !== 'none';
|
|
15751
|
+
}
|
|
15752
|
+
|
|
15753
|
+
const ERROR_TEXT_TIMEOUT = 500;
|
|
15754
|
+
// Map of view properties and related commands.
|
|
15755
|
+
const propertyToCommandMap = {
|
|
15756
|
+
borderStyle: 'tableCellBorderStyle',
|
|
15757
|
+
borderColor: 'tableCellBorderColor',
|
|
15758
|
+
borderWidth: 'tableCellBorderWidth',
|
|
15759
|
+
height: 'tableCellHeight',
|
|
15760
|
+
width: 'tableCellWidth',
|
|
15761
|
+
padding: 'tableCellPadding',
|
|
15762
|
+
backgroundColor: 'tableCellBackgroundColor',
|
|
15763
|
+
horizontalAlignment: 'tableCellHorizontalAlignment',
|
|
15764
|
+
verticalAlignment: 'tableCellVerticalAlignment',
|
|
15765
|
+
cellType: 'tableCellType'
|
|
15766
|
+
};
|
|
15767
|
+
/**
|
|
15768
|
+
* The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
|
|
15769
|
+
* that opens a form allowing to specify the visual styling of a table cell.
|
|
15770
|
+
*
|
|
15771
|
+
* It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
|
|
15772
|
+
*/ class TableCellPropertiesUIExperimental extends Plugin {
|
|
15773
|
+
/**
|
|
15774
|
+
* The default table cell properties.
|
|
15775
|
+
*/ _defaultContentTableCellProperties;
|
|
15776
|
+
/**
|
|
15777
|
+
* The default layout table cell properties.
|
|
15778
|
+
*/ _defaultLayoutTableCellProperties;
|
|
15779
|
+
/**
|
|
15780
|
+
* The contextual balloon plugin instance.
|
|
15781
|
+
*/ _balloon;
|
|
15782
|
+
/**
|
|
15783
|
+
* The cell properties form view displayed inside the balloon.
|
|
15784
|
+
*/ view;
|
|
15785
|
+
/**
|
|
15786
|
+
* The cell properties form view displayed inside the balloon (content table).
|
|
15787
|
+
*/ _viewWithContentTableDefaults;
|
|
15788
|
+
/**
|
|
15789
|
+
* The cell properties form view displayed inside the balloon (layout table).
|
|
15790
|
+
*/ _viewWithLayoutTableDefaults;
|
|
15791
|
+
/**
|
|
15792
|
+
* The batch used to undo all changes made by the form (which are live, as the user types)
|
|
15793
|
+
* when "Cancel" was pressed. Each time the view is shown, a new batch is created.
|
|
15794
|
+
*/ _undoStepBatch;
|
|
15795
|
+
/**
|
|
15796
|
+
* Flag used to indicate whether view is ready to execute update commands
|
|
15797
|
+
* (it finished loading initial data).
|
|
15798
|
+
*/ _isReady;
|
|
15799
|
+
/**
|
|
15800
|
+
* @inheritDoc
|
|
15801
|
+
*/ static get requires() {
|
|
15802
|
+
return [
|
|
15803
|
+
ContextualBalloon
|
|
15804
|
+
];
|
|
15805
|
+
}
|
|
15806
|
+
/**
|
|
15807
|
+
* @inheritDoc
|
|
15808
|
+
*/ static get pluginName() {
|
|
15809
|
+
return 'TableCellPropertiesUIExperimental';
|
|
15810
|
+
}
|
|
15811
|
+
/**
|
|
15812
|
+
* @inheritDoc
|
|
15813
|
+
*/ static get isOfficialPlugin() {
|
|
15814
|
+
return true;
|
|
15815
|
+
}
|
|
15816
|
+
/**
|
|
15817
|
+
* @inheritDoc
|
|
15818
|
+
*/ constructor(editor){
|
|
15819
|
+
super(editor);
|
|
15820
|
+
editor.config.define('table.tableCellProperties', {
|
|
15821
|
+
borderColors: defaultColors,
|
|
15822
|
+
backgroundColors: defaultColors
|
|
15823
|
+
});
|
|
15824
|
+
}
|
|
15825
|
+
/**
|
|
15826
|
+
* @inheritDoc
|
|
15827
|
+
*/ init() {
|
|
15828
|
+
const editor = this.editor;
|
|
15829
|
+
const t = editor.t;
|
|
15830
|
+
this._defaultContentTableCellProperties = getNormalizedDefaultCellProperties(editor.config.get('table.tableCellProperties.defaultProperties'), {
|
|
15831
|
+
includeVerticalAlignmentProperty: true,
|
|
15832
|
+
includeHorizontalAlignmentProperty: true,
|
|
15833
|
+
includePaddingProperty: true,
|
|
15834
|
+
isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl'
|
|
15835
|
+
});
|
|
15836
|
+
this._defaultLayoutTableCellProperties = getNormalizedDefaultProperties(undefined, {
|
|
15837
|
+
includeVerticalAlignmentProperty: true,
|
|
15838
|
+
includeHorizontalAlignmentProperty: true,
|
|
15839
|
+
isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl'
|
|
15840
|
+
});
|
|
15841
|
+
this._balloon = editor.plugins.get(ContextualBalloon);
|
|
15842
|
+
this.view = null;
|
|
15843
|
+
this._isReady = false;
|
|
15844
|
+
editor.ui.componentFactory.add('tableCellProperties', (locale)=>{
|
|
15845
|
+
const view = new ButtonView(locale);
|
|
15846
|
+
view.set({
|
|
15847
|
+
label: t('Cell properties'),
|
|
15848
|
+
icon: IconTableCellProperties,
|
|
15849
|
+
tooltip: true
|
|
15850
|
+
});
|
|
15851
|
+
this.listenTo(view, 'execute', ()=>this._showView());
|
|
15852
|
+
const commands = Object.values(propertyToCommandMap).map((commandName)=>editor.commands.get(commandName)).filter((val)=>!!val);
|
|
15853
|
+
view.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled)=>areEnabled.some((isCommandEnabled)=>isCommandEnabled));
|
|
15854
|
+
return view;
|
|
15855
|
+
});
|
|
15856
|
+
}
|
|
15857
|
+
/**
|
|
15858
|
+
* @inheritDoc
|
|
15859
|
+
*/ destroy() {
|
|
15860
|
+
super.destroy();
|
|
15861
|
+
// Destroy created UI components as they are not automatically destroyed.
|
|
15862
|
+
// See https://github.com/ckeditor/ckeditor5/issues/1341.
|
|
15863
|
+
if (this.view) {
|
|
15864
|
+
this.view.destroy();
|
|
15865
|
+
}
|
|
15866
|
+
}
|
|
15867
|
+
/**
|
|
15868
|
+
* Creates the {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView} instance.
|
|
15869
|
+
*
|
|
15870
|
+
* @returns The cell properties form view instance.
|
|
15871
|
+
*/ _createPropertiesView(defaultTableCellProperties) {
|
|
15872
|
+
const editor = this.editor;
|
|
15873
|
+
const config = editor.config.get('table.tableCellProperties');
|
|
15874
|
+
const borderColorsConfig = normalizeColorOptions(config.borderColors);
|
|
15875
|
+
const localizedBorderColors = getLocalizedColorOptions(editor.locale, borderColorsConfig);
|
|
15876
|
+
const backgroundColorsConfig = normalizeColorOptions(config.backgroundColors);
|
|
15877
|
+
const localizedBackgroundColors = getLocalizedColorOptions(editor.locale, backgroundColorsConfig);
|
|
15878
|
+
const hasColorPicker = config.colorPicker !== false;
|
|
15879
|
+
const isTableCellTypeSupported = !!editor.config.get('experimentalFlags.tableCellTypeSupport');
|
|
15880
|
+
const view = new TableCellPropertiesViewExperimental(editor.locale, {
|
|
15881
|
+
borderColors: localizedBorderColors,
|
|
15882
|
+
backgroundColors: localizedBackgroundColors,
|
|
15883
|
+
defaultTableCellProperties,
|
|
15884
|
+
colorPickerConfig: hasColorPicker ? config.colorPicker || {} : false,
|
|
15885
|
+
isTableCellTypeSupported
|
|
15886
|
+
});
|
|
15887
|
+
const t = editor.t;
|
|
15888
|
+
// Render the view so its #element is available for the clickOutsideHandler.
|
|
15889
|
+
view.render();
|
|
15890
|
+
this.listenTo(view, 'submit', ()=>{
|
|
15891
|
+
this._hideView();
|
|
15892
|
+
});
|
|
15893
|
+
this.listenTo(view, 'cancel', ()=>{
|
|
15894
|
+
// https://github.com/ckeditor/ckeditor5/issues/6180
|
|
15895
|
+
if (this._undoStepBatch.operations.length) {
|
|
15896
|
+
editor.execute('undo', this._undoStepBatch);
|
|
15897
|
+
}
|
|
15898
|
+
this._hideView();
|
|
15899
|
+
});
|
|
15900
|
+
// Close the balloon on Esc key press.
|
|
15901
|
+
view.keystrokes.set('Esc', (data, cancel)=>{
|
|
15902
|
+
this._hideView();
|
|
15903
|
+
cancel();
|
|
15904
|
+
});
|
|
15905
|
+
// Close on click outside of balloon panel element.
|
|
15906
|
+
clickOutsideHandler({
|
|
15907
|
+
emitter: view,
|
|
15908
|
+
activator: ()=>this._isViewInBalloon,
|
|
15909
|
+
contextElements: [
|
|
15910
|
+
this._balloon.view.element
|
|
15911
|
+
],
|
|
15912
|
+
callback: ()=>this._hideView()
|
|
15913
|
+
});
|
|
15914
|
+
const colorErrorText = getLocalizedColorErrorText(t);
|
|
15915
|
+
const lengthErrorText = getLocalizedLengthErrorText(t);
|
|
15916
|
+
// Create the "UI -> editor data" binding.
|
|
15917
|
+
// These listeners update the editor data (via table commands) when any observable
|
|
15918
|
+
// property of the view has changed. They also validate the value and display errors in the UI
|
|
15919
|
+
// when necessary. This makes the view live, which means the changes are
|
|
15920
|
+
// visible in the editing as soon as the user types or changes fields' values.
|
|
15921
|
+
view.on('change:borderStyle', this._getPropertyChangeCallback('tableCellBorderStyle'));
|
|
15922
|
+
view.on('change:borderColor', this._getValidatedPropertyChangeCallback({
|
|
15923
|
+
viewField: view.borderColorInput,
|
|
15924
|
+
commandName: 'tableCellBorderColor',
|
|
15925
|
+
errorText: colorErrorText,
|
|
15926
|
+
validator: colorFieldValidator
|
|
15927
|
+
}));
|
|
15928
|
+
view.on('change:borderWidth', this._getValidatedPropertyChangeCallback({
|
|
15929
|
+
viewField: view.borderWidthInput,
|
|
15930
|
+
commandName: 'tableCellBorderWidth',
|
|
15931
|
+
errorText: lengthErrorText,
|
|
15932
|
+
validator: lineWidthFieldValidator
|
|
15933
|
+
}));
|
|
15934
|
+
view.on('change:padding', this._getValidatedPropertyChangeCallback({
|
|
15935
|
+
viewField: view.paddingInput,
|
|
15936
|
+
commandName: 'tableCellPadding',
|
|
15937
|
+
errorText: lengthErrorText,
|
|
15938
|
+
validator: lengthFieldValidator
|
|
15939
|
+
}));
|
|
15940
|
+
view.on('change:width', this._getValidatedPropertyChangeCallback({
|
|
15941
|
+
viewField: view.widthInput,
|
|
15942
|
+
commandName: 'tableCellWidth',
|
|
15943
|
+
errorText: lengthErrorText,
|
|
15944
|
+
validator: lengthFieldValidator
|
|
15945
|
+
}));
|
|
15946
|
+
view.on('change:height', this._getValidatedPropertyChangeCallback({
|
|
15947
|
+
viewField: view.heightInput,
|
|
15948
|
+
commandName: 'tableCellHeight',
|
|
15949
|
+
errorText: lengthErrorText,
|
|
15950
|
+
validator: lengthFieldValidator
|
|
15951
|
+
}));
|
|
15952
|
+
view.on('change:backgroundColor', this._getValidatedPropertyChangeCallback({
|
|
15953
|
+
viewField: view.backgroundInput,
|
|
15954
|
+
commandName: 'tableCellBackgroundColor',
|
|
15955
|
+
errorText: colorErrorText,
|
|
15956
|
+
validator: colorFieldValidator
|
|
15957
|
+
}));
|
|
15958
|
+
view.on('change:horizontalAlignment', this._getPropertyChangeCallback('tableCellHorizontalAlignment'));
|
|
15959
|
+
view.on('change:verticalAlignment', this._getPropertyChangeCallback('tableCellVerticalAlignment'));
|
|
15960
|
+
const cellTypeCommand = editor.commands.get('tableCellType');
|
|
15961
|
+
if (cellTypeCommand) {
|
|
15962
|
+
view.cellTypeDropdown.bind('isEnabled').to(cellTypeCommand, 'isEnabled');
|
|
15963
|
+
view.on('change:cellType', this._getPropertyChangeCallback('tableCellType'));
|
|
15964
|
+
}
|
|
15965
|
+
return view;
|
|
15966
|
+
}
|
|
15967
|
+
/**
|
|
15968
|
+
* In this method the "editor data -> UI" binding is happening.
|
|
15969
|
+
*
|
|
15970
|
+
* When executed, this method obtains selected cell property values from various table commands
|
|
15971
|
+
* and passes them to the {@link #view}.
|
|
15972
|
+
*
|
|
15973
|
+
* This way, the UI stays up–to–date with the editor data.
|
|
15974
|
+
*/ _fillViewFormFromCommandValues() {
|
|
15975
|
+
const commands = this.editor.commands;
|
|
15976
|
+
const borderStyleCommand = commands.get('tableCellBorderStyle');
|
|
15977
|
+
Object.entries(propertyToCommandMap).flatMap(([property, commandName])=>{
|
|
15978
|
+
const command = commands.get(commandName);
|
|
15979
|
+
if (!command) {
|
|
15980
|
+
return [];
|
|
15981
|
+
}
|
|
15982
|
+
const propertyKey = property;
|
|
15983
|
+
let defaultValue;
|
|
15984
|
+
if (propertyKey === 'cellType') {
|
|
15985
|
+
defaultValue = '';
|
|
15986
|
+
} else {
|
|
15987
|
+
defaultValue = this.view === this._viewWithContentTableDefaults ? this._defaultContentTableCellProperties[propertyKey] || '' : this._defaultLayoutTableCellProperties[propertyKey] || '';
|
|
15988
|
+
}
|
|
15989
|
+
const entry = [
|
|
15990
|
+
property,
|
|
15991
|
+
command.value || defaultValue
|
|
15992
|
+
];
|
|
15993
|
+
return [
|
|
15994
|
+
entry
|
|
15995
|
+
];
|
|
15996
|
+
}).forEach(([property, value])=>{
|
|
15997
|
+
// Do not set the `border-color` and `border-width` fields if `border-style:none`.
|
|
15998
|
+
if ((property === 'borderColor' || property === 'borderWidth') && borderStyleCommand.value === 'none') {
|
|
15999
|
+
return;
|
|
16000
|
+
}
|
|
16001
|
+
this.view.set(property, value);
|
|
16002
|
+
});
|
|
16003
|
+
this._isReady = true;
|
|
16004
|
+
}
|
|
16005
|
+
/**
|
|
16006
|
+
* Shows the {@link #view} in the {@link #_balloon}.
|
|
16007
|
+
*
|
|
16008
|
+
* **Note**: Each time a view is shown, a new {@link #_undoStepBatch} is created. It contains
|
|
16009
|
+
* all changes made to the document when the view is visible, allowing a single undo step
|
|
16010
|
+
* for all of them.
|
|
16011
|
+
*/ _showView() {
|
|
16012
|
+
const editor = this.editor;
|
|
16013
|
+
const viewTable = getSelectionAffectedTableWidget(editor.editing.view.document.selection);
|
|
16014
|
+
const modelTable = viewTable && editor.editing.mapper.toModelElement(viewTable);
|
|
16015
|
+
const useDefaults = !modelTable || modelTable.getAttribute('tableType') !== 'layout';
|
|
16016
|
+
if (useDefaults && !this._viewWithContentTableDefaults) {
|
|
16017
|
+
this._viewWithContentTableDefaults = this._createPropertiesView(this._defaultContentTableCellProperties);
|
|
16018
|
+
} else if (!useDefaults && !this._viewWithLayoutTableDefaults) {
|
|
16019
|
+
this._viewWithLayoutTableDefaults = this._createPropertiesView(this._defaultLayoutTableCellProperties);
|
|
16020
|
+
}
|
|
16021
|
+
this.view = useDefaults ? this._viewWithContentTableDefaults : this._viewWithLayoutTableDefaults;
|
|
16022
|
+
this.listenTo(editor.ui, 'update', ()=>{
|
|
16023
|
+
this._updateView();
|
|
16024
|
+
});
|
|
16025
|
+
// Update the view with the model values.
|
|
16026
|
+
this._fillViewFormFromCommandValues();
|
|
16027
|
+
this._balloon.add({
|
|
16028
|
+
view: this.view,
|
|
16029
|
+
position: getBalloonCellPositionData(editor)
|
|
16030
|
+
});
|
|
16031
|
+
// Create a new batch. Clicking "Cancel" will undo this batch.
|
|
16032
|
+
this._undoStepBatch = editor.model.createBatch();
|
|
16033
|
+
// Basic a11y.
|
|
16034
|
+
this.view.focus();
|
|
16035
|
+
}
|
|
16036
|
+
/**
|
|
16037
|
+
* Removes the {@link #view} from the {@link #_balloon}.
|
|
16038
|
+
*/ _hideView() {
|
|
16039
|
+
const editor = this.editor;
|
|
16040
|
+
this.stopListening(editor.ui, 'update');
|
|
16041
|
+
this._isReady = false;
|
|
16042
|
+
// Blur any input element before removing it from DOM to prevent issues in some browsers.
|
|
16043
|
+
// See https://github.com/ckeditor/ckeditor5/issues/1501.
|
|
16044
|
+
this.view.saveButtonView.focus();
|
|
16045
|
+
this._balloon.remove(this.view);
|
|
16046
|
+
// Make sure the focus is not lost in the process by putting it directly
|
|
16047
|
+
// into the editing view.
|
|
16048
|
+
this.editor.editing.view.focus();
|
|
16049
|
+
}
|
|
16050
|
+
/**
|
|
16051
|
+
* Repositions the {@link #_balloon} or hides the {@link #view} if a table cell is no longer selected.
|
|
16052
|
+
*/ _updateView() {
|
|
16053
|
+
const editor = this.editor;
|
|
16054
|
+
const viewDocument = editor.editing.view.document;
|
|
16055
|
+
if (!getTableWidgetAncestor(viewDocument.selection)) {
|
|
16056
|
+
this._hideView();
|
|
16057
|
+
} else if (this._isViewVisible) {
|
|
16058
|
+
repositionContextualBalloon(editor, 'cell');
|
|
16059
|
+
}
|
|
16060
|
+
}
|
|
16061
|
+
/**
|
|
16062
|
+
* Returns `true` when the {@link #view} is visible in the {@link #_balloon}.
|
|
16063
|
+
*/ get _isViewVisible() {
|
|
16064
|
+
return !!this.view && this._balloon.visibleView === this.view;
|
|
16065
|
+
}
|
|
16066
|
+
/**
|
|
16067
|
+
* Returns `true` when the {@link #view} is in the {@link #_balloon}.
|
|
16068
|
+
*/ get _isViewInBalloon() {
|
|
16069
|
+
return !!this.view && this._balloon.hasView(this.view);
|
|
16070
|
+
}
|
|
16071
|
+
/**
|
|
16072
|
+
* Creates a callback that when executed upon the {@link #view view's} property change
|
|
16073
|
+
* executes a related editor command with the new property value.
|
|
16074
|
+
*
|
|
16075
|
+
* @param commandName The default value of the command.
|
|
16076
|
+
*/ _getPropertyChangeCallback(commandName) {
|
|
16077
|
+
return (evt, propertyName, newValue)=>{
|
|
16078
|
+
if (!this._isReady) {
|
|
16079
|
+
return;
|
|
16080
|
+
}
|
|
16081
|
+
this.editor.execute(commandName, {
|
|
16082
|
+
value: newValue,
|
|
16083
|
+
batch: this._undoStepBatch
|
|
16084
|
+
});
|
|
16085
|
+
};
|
|
16086
|
+
}
|
|
16087
|
+
/**
|
|
16088
|
+
* Creates a callback that when executed upon the {@link #view view's} property change:
|
|
16089
|
+
* * Executes a related editor command with the new property value if the value is valid,
|
|
16090
|
+
* * Or sets the error text next to the invalid field, if the value did not pass the validation.
|
|
16091
|
+
*/ _getValidatedPropertyChangeCallback(options) {
|
|
16092
|
+
const { commandName, viewField, validator, errorText } = options;
|
|
16093
|
+
const setErrorTextDebounced = debounce(()=>{
|
|
16094
|
+
viewField.errorText = errorText;
|
|
16095
|
+
}, ERROR_TEXT_TIMEOUT);
|
|
16096
|
+
return (evt, propertyName, newValue)=>{
|
|
16097
|
+
setErrorTextDebounced.cancel();
|
|
16098
|
+
// Do not execute the command on initial call (opening the table properties view).
|
|
16099
|
+
if (!this._isReady) {
|
|
16100
|
+
return;
|
|
16101
|
+
}
|
|
16102
|
+
if (validator(newValue)) {
|
|
16103
|
+
this.editor.execute(commandName, {
|
|
16104
|
+
value: newValue,
|
|
16105
|
+
batch: this._undoStepBatch
|
|
16106
|
+
});
|
|
16107
|
+
viewField.errorText = null;
|
|
16108
|
+
} else {
|
|
16109
|
+
setErrorTextDebounced();
|
|
16110
|
+
}
|
|
16111
|
+
};
|
|
16112
|
+
}
|
|
16113
|
+
}
|
|
16114
|
+
|
|
16115
|
+
export { InsertColumnCommand, InsertRowCommand, InsertTableCommand, InsertTableLayoutCommand, MergeCellCommand, MergeCellsCommand, PlainTableOutput, RemoveColumnCommand, RemoveRowCommand, SelectColumnCommand, SelectRowCommand, SetHeaderColumnCommand, SetHeaderRowCommand, SplitCellCommand, Table, TableAlignmentCommand, TableBackgroundColorCommand, TableBorderColorCommand, TableBorderStyleCommand, TableBorderWidthCommand, TableCaption, TableCaptionEditing, TableCaptionUI, TableCellBackgroundColorCommand, TableCellBorderColorCommand, TableCellBorderStyleCommand, TableCellBorderWidthCommand, TableCellHeightCommand, TableCellHorizontalAlignmentCommand, TableCellPaddingCommand, TableCellProperties, TableCellPropertiesEditing, TableCellPropertiesUI, TableCellPropertiesUIExperimental, TableCellPropertiesView, TableCellPropertiesViewExperimental, TableCellPropertyCommand, TableCellTypeCommand, TableCellVerticalAlignmentCommand, TableCellWidthCommand, TableCellWidthEditing, TableClipboard, TableColumnResize, TableColumnResizeEditing, TableEditing, TableHeightCommand, TableKeyboard, TableLayout, TableLayoutEditing, TableLayoutUI, TableMouse, TableProperties, TablePropertiesEditing, TablePropertiesUI, TablePropertiesUIExperimental, TablePropertiesView, TablePropertiesViewExperimental, TablePropertyCommand, TableSelection, TableToolbar, TableTypeCommand, TableUI, TableUtils, TableWalker, TableWidthCommand, TableWidthsCommand, ToggleTableCaptionCommand, InsertTableView as _InsertTableView, COLUMN_MIN_WIDTH_AS_PERCENTAGE as _TABLE_COLUMN_MIN_WIDTH_AS_PERCENTAGE, COLUMN_MIN_WIDTH_IN_PIXELS as _TABLE_COLUMN_MIN_WIDTH_IN_PIXELS, COLUMN_RESIZE_DISTANCE_THRESHOLD as _TABLE_COLUMN_RESIZE_DISTANCE_THRESHOLD, COLUMN_WIDTH_PRECISION as _TABLE_COLUMN_WIDTH_PRECISION, defaultColors as _TABLE_DEFAULT_COLORS, ColorInputView as _TableColorInputView, MouseEventsObserver as _TableMouseEventsObserver, addDefaultUnitToNumericValue as _addDefaultUnitToNumericValue, adjustLastColumnIndex as _adjustLastTableColumnIndex, adjustLastRowIndex as _adjustLastTableRowIndex, clamp as _clamp, colorFieldValidator as _colorTableFieldValidator, convertParagraphInTableCell as _convertParagraphInTableCell, createEmptyTableCell as _createEmptyTableCell, createFilledArray as _createFilledArray, cropTableToDimensions as _cropTableToDimensions, downcastTable as _downcastTable, downcastTableAttribute as _downcastTableAttribute, downcastAttributeToStyle as _downcastTableAttributeToStyle, downcastCell as _downcastTableCell, downcastTableResizedClass as _downcastTableResizedClass, downcastRow as _downcastTableRow, enableProperty$1 as _enableTableCellProperty, ensureParagraphInTableCell as _ensureParagraphInTableCell, fillToolbar$1 as _fillTableOrCellToolbar, getBalloonCellPositionData as _getBalloonTableCellPositionData, getBalloonTablePositionData as _getBalloonTablePositionData, getBorderStyleLabels$1 as _getBorderTableStyleLabels, getChangedResizedTables as _getChangedResizedTables, getDefaultValueAdjusted as _getDefaultTableValueAdjusted, getDomCellOuterWidth as _getDomTableCellOuterWidth, getElementWidthInPixels as _getElementWidthInPixels, getHorizontallyOverlappingCells as _getHorizontallyOverlappingTableCells, getLabeledColorInputCreator$1 as _getLabeledTableColorInputCreator, getLocalizedColorErrorText as _getLocalizedTableColorErrorText, getLocalizedLengthErrorText as _getLocalizedTableLengthErrorText, getNormalizedDefaultProperties as _getNormalizedDefaultTableBaseProperties, getNormalizedDefaultCellProperties as _getNormalizedDefaultTableCellProperties, getNormalizedDefaultTableProperties as _getNormalizedDefaultTableProperties, getSelectedTableWidget as _getSelectedTableWidget, getSelectionAffectedTable as _getSelectionAffectedTable, getSelectionAffectedTableWidget as _getSelectionAffectedTableWidget, getSingleValue as _getTableBorderBoxSingleValue, getCaptionFromTableModelElement as _getTableCaptionFromModelElement, getCaptionFromModelSelection as _getTableCaptionFromModelSelection, getColumnEdgesIndexes as _getTableColumnEdgesIndexes, getTableColumnElements as _getTableColumnElements, getColumnGroupElement as _getTableColumnGroupElement, getColumnMinWidthAsPercentage as _getTableColumnMinWidthAsPercentage, getTableColumnsWidths as _getTableColumnsWidths, getBorderStyleDefinitions$1 as _getTableOrCellBorderStyleDefinitions, getTableWidgetAncestor as _getTableWidgetAncestor, getTableWidthInPixels as _getTableWidthInPixels, getVerticallyOverlappingCells as _getVerticallyOverlappingTableCells, injectTableCaptionPostFixer as _injectTableCaptionPostFixer, injectTableCellParagraphPostFixer as _injectTableCellParagraphPostFixer, injectTableLayoutPostFixer as _injectTableLayoutPostFixer, isSingleParagraphWithoutAttributes as _isSingleTableParagraphWithoutAttributes, isHeadingColumnCell as _isTableHeadingColumnCell, isTable as _isTableModelElement, lengthFieldValidator as _lengthTableFieldValidator, lineWidthFieldValidator as _lineWidthTableFieldValidator, matchTableCaptionViewElement as _matchTableCaptionViewElement, normalizeColumnWidths as _normalizeTableColumnWidths, removeEmptyColumns as _removeEmptyTableColumns, removeEmptyRows as _removeEmptyTableRows, removeEmptyRowsColumns as _removeEmptyTableRowsColumns, repositionContextualBalloon as _repositionTableContextualBalloon, skipEmptyTableRow as _skipEmptyTableRow, splitHorizontally as _splitTableCellHorizontally, splitVertically as _splitTableCellVertically, sumArray as _sumArray, tableCellRefreshHandler as _tableCellRefreshHandler, tableHeadingsRefreshHandler as _tableHeadingsRefreshHandler, toPrecision as _toPrecision, translateColSpanAttribute as _translateTableColspanAttribute, trimTableCellIfNeeded as _trimTableCellIfNeeded, upcastStyleToAttribute as _upcastNormalizedTableStyleToAttribute, upcastTable as _upcastTable, upcastBorderStyles as _upcastTableBorderStyles, upcastColgroupElement as _upcastTableColgroupElement, upcastTableFigure as _upcastTableFigure, updateColumnElements as _updateTableColumnElements, updateNumericAttribute as _updateTableNumericAttribute };
|
|
14131
16116
|
//# sourceMappingURL=index.js.map
|