qms-angular 1.1.76 → 1.1.77

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.
Files changed (29) hide show
  1. package/bundles/qms-angular.umd.js +18 -7
  2. package/bundles/qms-angular.umd.js.map +1 -1
  3. package/esm2015/lib/model/en.js +6 -2
  4. package/esm2015/lib/model/no.js +6 -2
  5. package/esm2015/lib/qms-ckeditor-components/common/functions/resource.function.js +9 -6
  6. package/fesm2015/qms-angular.js +18 -7
  7. package/fesm2015/qms-angular.js.map +1 -1
  8. package/lib/model/en.d.ts +4 -0
  9. package/lib/model/no.d.ts +4 -0
  10. package/lib/qms-ckeditor-components/common/functions/resource.function.d.ts +8 -5
  11. package/package.json +1 -1
  12. package/qms-angular.metadata.json +1 -1
  13. package/src/assets/qms-ckeditor-plugin/build/ckeditor.js +2 -2
  14. package/src/assets/qms-ckeditor-plugin/build/ckeditor.js.map +1 -1
  15. package/src/assets/qms-ckeditor-plugin/src/ckeditor.js +6 -2
  16. package/src/assets/qms-ckeditor-plugin/src/plugins/collapsible/collapsible.js +229 -0
  17. package/src/assets/qms-ckeditor-plugin/src/plugins/collapsible/collapsiblecommand.js +13 -0
  18. package/src/assets/qms-ckeditor-plugin/src/plugins/heading/headingediting.js +165 -163
  19. package/src/assets/qms-ckeditor-plugin/src/plugins/heading/headingui.js +18 -8
  20. package/src/assets/qms-ckeditor-plugin/src/plugins/heading/ingress/ingress.js +63 -0
  21. package/src/assets/qms-ckeditor-plugin/src/plugins/heading/ingress/ingresscommand.js +33 -0
  22. package/src/assets/qms-ckeditor-plugin/src/plugins/heading/theme/heading.css +44 -35
  23. package/src/assets/qms-ckeditor-plugin/src/plugins/heading/utils.js +2 -1
  24. package/src/assets/qms-ckeditor-plugin/src/plugins/table/commands/setheadercolumncommand.js +99 -95
  25. package/src/assets/qms-ckeditor-plugin/src/plugins/table/commands/setheaderrowcommand.js +110 -105
  26. package/src/assets/qms-ckeditor-plugin/src/plugins/table/converters/downcast.js +529 -529
  27. package/src/assets/qms-ckeditor-plugin/src/plugins/table/theme/table.css +67 -67
  28. package/src/assets/qms-ckeditor-plugin/src/plugins/tooltip/tooltipcommand.js +74 -75
  29. package/src/assets/qms-ckeditor-plugin/src/themes/icons/angles-up-down.svg +1 -0
@@ -45,8 +45,9 @@ export default class HeadingUI extends Plugin {
45
45
 
46
46
  const headingCommand = editor.commands.get( 'heading' );
47
47
  const paragraphCommand = editor.commands.get( 'paragraph' );
48
+ const ingressCommand = editor.commands.get( 'ingress' );
48
49
 
49
- const commands = [ headingCommand ];
50
+ const commands = [ headingCommand, ingressCommand ];
50
51
 
51
52
  for ( const option of options ) {
52
53
  const def = {
@@ -58,10 +59,19 @@ export default class HeadingUI extends Plugin {
58
59
  } )
59
60
  };
60
61
 
61
- if ( option.model === 'paragraph' ) {
62
- def.model.bind( 'isOn' ).to( paragraphCommand, 'value' );
63
- def.model.set( 'commandName', 'paragraph' );
64
- commands.push( paragraphCommand );
62
+ if ( option.model === 'paragraph' || option.model === 'ingress' ) {
63
+ if(option.model === 'paragraph'){
64
+ def.model.bind( 'isOn' ).to( paragraphCommand, 'value' );
65
+ def.model.set( 'commandName', 'paragraph' );
66
+ commands.push( paragraphCommand );
67
+ }
68
+ if ( option.model === 'ingress' ) {
69
+ def.model.bind( 'isOn' ).to( ingressCommand, 'value', value => value === option.model );
70
+ def.model.set( {
71
+ commandName: 'ingress',
72
+ commandValue: option.model
73
+ } );
74
+ }
65
75
  } else {
66
76
  def.model.bind( 'isOn' ).to( headingCommand, 'value', value => value === option.model );
67
77
  def.model.set( {
@@ -97,12 +107,12 @@ export default class HeadingUI extends Plugin {
97
107
  return areEnabled.some( isEnabled => isEnabled );
98
108
  } );
99
109
 
100
- dropdownView.buttonView.bind( 'label' ).to( headingCommand, 'value', paragraphCommand, 'value', ( value, para ) => {
101
- const whichModel = value || para && 'paragraph';
110
+ dropdownView.buttonView.bind( 'label' ).to( headingCommand, 'value', paragraphCommand, 'value',ingressCommand, 'value', ( head, para, ingrs ) => {
111
+ const whichModel = head || ingrs && 'ingress' || para && 'paragraph';
102
112
  // If none of the commands is active, display default title.
103
113
  return titles[ whichModel ] ? titles[ whichModel ] : defaultTitle;
104
114
  } );
105
-
115
+
106
116
  // Execute command when an item from the dropdown is selected.
107
117
  this.listenTo( dropdownView, 'execute', evt => {
108
118
  editor.execute( evt.source.commandName, evt.source.commandValue ? { value: evt.source.commandValue } : undefined );
@@ -0,0 +1,63 @@
1
+ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
2
+ import IngressCommand from './ingresscommand';
3
+
4
+ export default class Ingress extends Plugin {
5
+
6
+ static get pluginName() {
7
+ return 'Ingress';
8
+ }
9
+
10
+ init() {
11
+ const editor = this.editor;
12
+ const model = editor.model;
13
+
14
+ editor.commands.add( 'ingress', new IngressCommand( editor ) );
15
+
16
+ // Schema.
17
+ model.schema.register( 'ingress', { inheritAllFrom: '$block' } );
18
+ editor.conversion.elementToElement( { model: 'ingress', view: 'p' } );
19
+
20
+ // Conversion for paragraph-like elements which has not been converted by any plugin.
21
+ // editor.conversion.for( 'upcast' ).elementToElement( {
22
+ // model: ( viewElement, { writer } ) => {
23
+ // if ( !Ingress.paragraphLikeElements.has( viewElement.name ) ) {
24
+ // return null;
25
+ // }
26
+
27
+ // // Do not auto-paragraph empty elements.
28
+ // if ( viewElement.isEmpty ) {
29
+ // return null;
30
+ // }
31
+
32
+ // return writer.createElement( 'ingress' );
33
+ // },
34
+ // view: /.+/,
35
+ // converterPriority: 'low'
36
+ // } );
37
+
38
+ editor.conversion.for( 'downcast' ).add( dispatcher => {
39
+ dispatcher.on( 'insert:ingress', ( evt, data, conversionApi ) => {
40
+ const viewWriter = conversionApi.writer;
41
+
42
+ viewWriter.addClass( 'radEdIngress', conversionApi.mapper.toViewElement( data.item ) );
43
+ }, { priority: 'low' } );
44
+ } );
45
+ }
46
+ }
47
+
48
+ Ingress.paragraphLikeElements = new Set( [
49
+ 'blockquote',
50
+ 'dd',
51
+ 'div',
52
+ 'dt',
53
+ 'h1',
54
+ 'h2',
55
+ 'h3',
56
+ 'h4',
57
+ 'h5',
58
+ 'h6',
59
+ 'li',
60
+ 'p',
61
+ 'td',
62
+ 'th'
63
+ ] );
@@ -0,0 +1,33 @@
1
+ import Command from '@ckeditor/ckeditor5-core/src/command';
2
+ import first from '@ckeditor/ckeditor5-utils/src/first';
3
+
4
+
5
+ export default class IngressCommand extends Command {
6
+ refresh() {
7
+ const model = this.editor.model;
8
+ const document = model.document;
9
+ const block = first( document.selection.getSelectedBlocks() );
10
+
11
+ this.value = !!block && block.is( 'element', 'ingress' );
12
+ this.isEnabled = !!block && checkCanBecomeIngress( block, model.schema );
13
+ }
14
+
15
+ execute( options = {} ) {
16
+ const model = this.editor.model;
17
+ const document = model.document;
18
+
19
+ model.change( writer => {
20
+ const blocks = ( options.selection || document.selection ).getSelectedBlocks();
21
+
22
+ for ( const block of blocks ) {
23
+ if ( !block.is( 'element', 'ingress' ) && checkCanBecomeIngress( block, model.schema ) ) {
24
+ writer.rename( block, 'ingress' );
25
+ }
26
+ }
27
+ } );
28
+ }
29
+ }
30
+
31
+ function checkCanBecomeIngress( block, schema ) {
32
+ return schema.checkChild( block.parent, 'ingress' ) && !schema.isObject( block );
33
+ }
@@ -1,35 +1,44 @@
1
- /*
2
- * Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
- */
5
-
6
- .ck.ck-heading_heading1 {
7
- font-size: 20px;
8
- }
9
-
10
- .ck.ck-heading_heading2 {
11
- font-size: 17px;
12
- }
13
-
14
- .ck.ck-heading_heading3 {
15
- font-size: 14px;
16
- }
17
-
18
- .ck[class*="ck-heading_heading"] {
19
- font-weight: bold;
20
- }
21
-
22
- .ck h1.radEdH1{
23
- font: bold 14pt Cambria, sans-serif;
24
- color: #003388;
25
- }
26
-
27
- .ck h2.radEdH2{
28
- font: bold 13pt Cambria, sans-serif;
29
- color: #003388;
30
- }
31
-
32
- .ck h3.radEdH3{
33
- font: bold 12pt Cambria, sans-serif;
34
- color: #003388;
35
- }
1
+ /*
2
+ * Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ .ck.ck-heading_heading1 {
7
+ font-size: 20px;
8
+ }
9
+
10
+ .ck.ck-heading_heading2 {
11
+ font-size: 17px;
12
+ }
13
+
14
+ .ck.ck-heading_heading3 {
15
+ font-size: 14px;
16
+ }
17
+
18
+ .ck[class*="ck-heading_heading"] {
19
+ font-weight: bold;
20
+ }
21
+
22
+ .ck h1.radEdH1{
23
+ font: bold 14pt Cambria, sans-serif;
24
+ color: #003388;
25
+ }
26
+
27
+ .ck h2.radEdH2{
28
+ font: bold 13pt Cambria, sans-serif;
29
+ color: #003388;
30
+ }
31
+
32
+ .ck h3.radEdH3{
33
+ font: bold 12pt Cambria, sans-serif;
34
+ color: #003388;
35
+ }
36
+
37
+ .ck .ck-heading_ingress {
38
+ font-size: 20px !important;
39
+ font-weight: bold;
40
+ }
41
+
42
+ .radEdIngress{
43
+ font: bold 14pt Cambria, sans-serif;
44
+ }
@@ -21,7 +21,8 @@
21
21
  export function getLocalizedOptions( editor ) {
22
22
  const t = editor.t;
23
23
  const localizedTitles = {
24
- Paragraph: t( 'Paragraph' ),
24
+ Paragraph: t( 'Default' ),
25
+ Ingress: t( 'Ingress' ),
25
26
  'Heading 1': t( 'Heading %0', '1' ),
26
27
  'Heading 2': t( 'Heading %0', '2' ),
27
28
  'Heading 3': t( 'Heading %0', '3' ),
@@ -1,95 +1,99 @@
1
- /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
- */
5
-
6
- /**
7
- * @module table/commands/setheadercolumncommand
8
- */
9
-
10
- import { Command } from 'ckeditor5/src/core';
11
-
12
- import {
13
- isHeadingColumnCell,
14
- updateNumericAttribute
15
- } from '../utils/common';
16
- import { getColumnIndexes, getSelectionAffectedTableCells } from '../utils/selection';
17
- import { getHorizontallyOverlappingCells, splitVertically } from '../utils/structure';
18
-
19
- /**
20
- * The header column command.
21
- *
22
- * The command is registered by {@link module:table/tableediting~TableEditing} as the `'setTableColumnHeader'` editor command.
23
- *
24
- * You can make the column containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element)
25
- * by executing:
26
- *
27
- * editor.execute( 'setTableColumnHeader' );
28
- *
29
- * **Note:** All preceding columns will also become headers. If the current column is already a header, executing this command
30
- * will make it a regular column back again (including the following columns).
31
- *
32
- * @extends module:core/command~Command
33
- */
34
- export default class SetHeaderColumnCommand extends Command {
35
- /**
36
- * @inheritDoc
37
- */
38
- refresh() {
39
- const model = this.editor.model;
40
- const selectedCells = getSelectionAffectedTableCells( model.document.selection );
41
- const tableUtils = this.editor.plugins.get( 'TableUtils' );
42
- const isInTable = selectedCells.length > 0;
43
-
44
- this.isEnabled = isInTable;
45
-
46
- /**
47
- * Flag indicating whether the command is active. The command is active when the
48
- * {@link module:engine/model/selection~Selection} is in a header column.
49
- *
50
- * @observable
51
- * @readonly
52
- * @member {Boolean} #value
53
- */
54
- this.value = isInTable && selectedCells.every( cell => isHeadingColumnCell( tableUtils, cell ) );
55
- }
56
-
57
- /**
58
- * Executes the command.
59
- *
60
- * When the selection is in a non-header column, the command will set the `headingColumns` table attribute to cover that column.
61
- *
62
- * When the selection is already in a header column, it will set `headingColumns` so the heading section will end before that column.
63
- *
64
- * @fires execute
65
- * @param {Object} [options]
66
- * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) the header columns according to
67
- * the `forceValue` parameter instead of the current model state.
68
- */
69
- execute( options = {} ) {
70
- if ( options.forceValue === this.value ) {
71
- return;
72
- }
73
-
74
- const model = this.editor.model;
75
- const selectedCells = getSelectionAffectedTableCells( model.document.selection );
76
- const table = selectedCells[ 0 ].findAncestor( 'table' );
77
-
78
- const { first, last } = getColumnIndexes( selectedCells );
79
- const headingColumnsToSet = this.value ? first : last + 1;
80
-
81
- model.change( writer => {
82
- if ( headingColumnsToSet ) {
83
- // Changing heading columns requires to check if any of a heading cell is overlapping horizontally the table head.
84
- // Any table cell that has a colspan attribute > 1 will not exceed the table head so we need to fix it in columns before.
85
- const overlappingCells = getHorizontallyOverlappingCells( table, headingColumnsToSet );
86
-
87
- for ( const { cell, column } of overlappingCells ) {
88
- splitVertically( cell, column, headingColumnsToSet, writer );
89
- }
90
- }
91
-
92
- updateNumericAttribute( 'headingColumns', headingColumnsToSet, table, writer, 0 );
93
- } );
94
- }
95
- }
1
+ /**
2
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module table/commands/setheadercolumncommand
8
+ */
9
+
10
+ import { Command } from 'ckeditor5/src/core';
11
+
12
+ import {
13
+ isHeadingColumnCell,
14
+ updateNumericAttribute
15
+ } from '../utils/common';
16
+ import { getColumnIndexes, getSelectionAffectedTableCells } from '../utils/selection';
17
+ import { getHorizontallyOverlappingCells, splitVertically } from '../utils/structure';
18
+
19
+ /**
20
+ * The header column command.
21
+ *
22
+ * The command is registered by {@link module:table/tableediting~TableEditing} as the `'setTableColumnHeader'` editor command.
23
+ *
24
+ * You can make the column containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element)
25
+ * by executing:
26
+ *
27
+ * editor.execute( 'setTableColumnHeader' );
28
+ *
29
+ * **Note:** All preceding columns will also become headers. If the current column is already a header, executing this command
30
+ * will make it a regular column back again (including the following columns).
31
+ *
32
+ * @extends module:core/command~Command
33
+ */
34
+ export default class SetHeaderColumnCommand extends Command {
35
+ /**
36
+ * @inheritDoc
37
+ */
38
+ refresh() {
39
+ const model = this.editor.model;
40
+ const selectedCells = getSelectionAffectedTableCells( model.document.selection );
41
+ const tableUtils = this.editor.plugins.get( 'TableUtils' );
42
+ const isInTable = selectedCells.length > 0;
43
+
44
+ this.isEnabled = isInTable;
45
+
46
+ /**
47
+ * Flag indicating whether the command is active. The command is active when the
48
+ * {@link module:engine/model/selection~Selection} is in a header column.
49
+ *
50
+ * @observable
51
+ * @readonly
52
+ * @member {Boolean} #value
53
+ */
54
+ this.value = isInTable && selectedCells.every( cell => isHeadingColumnCell( tableUtils, cell ) );
55
+ }
56
+
57
+ /**
58
+ * Executes the command.
59
+ *
60
+ * When the selection is in a non-header column, the command will set the `headingColumns` table attribute to cover that column.
61
+ *
62
+ * When the selection is already in a header column, it will set `headingColumns` so the heading section will end before that column.
63
+ *
64
+ * @fires execute
65
+ * @param {Object} [options]
66
+ * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) the header columns according to
67
+ * the `forceValue` parameter instead of the current model state.
68
+ */
69
+ execute( options = {} ) {
70
+ if ( options.forceValue === this.value ) {
71
+ return;
72
+ }
73
+
74
+ const model = this.editor.model;
75
+ const selectedCells = getSelectionAffectedTableCells( model.document.selection );
76
+ const table = selectedCells[ 0 ].findAncestor( 'table' );
77
+
78
+ const { first, last } = getColumnIndexes( selectedCells );
79
+ const headingColumnsToSet = this.value ? first : last + 1;
80
+
81
+ model.change( writer => {
82
+ if(headingColumnsToSet > 1){
83
+ return;
84
+ }
85
+
86
+ if ( headingColumnsToSet ) {
87
+ // Changing heading columns requires to check if any of a heading cell is overlapping horizontally the table head.
88
+ // Any table cell that has a colspan attribute > 1 will not exceed the table head so we need to fix it in columns before.
89
+ const overlappingCells = getHorizontallyOverlappingCells( table, headingColumnsToSet );
90
+
91
+ for ( const { cell, column } of overlappingCells ) {
92
+ splitVertically( cell, column, headingColumnsToSet, writer );
93
+ }
94
+ }
95
+
96
+ updateNumericAttribute( 'headingColumns', headingColumnsToSet, table, writer, 0 );
97
+ } );
98
+ }
99
+ }
@@ -1,105 +1,110 @@
1
- /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
- */
5
-
6
- /**
7
- * @module table/commands/setheaderrowcommand
8
- */
9
-
10
- import { Command } from 'ckeditor5/src/core';
11
-
12
- import { updateNumericAttribute } from '../utils/common';
13
- import { getRowIndexes, getSelectionAffectedTableCells } from '../utils/selection';
14
- import { getVerticallyOverlappingCells, splitHorizontally } from '../utils/structure';
15
-
16
- /**
17
- * The header row command.
18
- *
19
- * The command is registered by {@link module:table/tableediting~TableEditing} as the `'setTableColumnHeader'` editor command.
20
- *
21
- * You can make the row containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element) by executing:
22
- *
23
- * editor.execute( 'setTableRowHeader' );
24
- *
25
- * **Note:** All preceding rows will also become headers. If the current row is already a header, executing this command
26
- * will make it a regular row back again (including the following rows).
27
- *
28
- * @extends module:core/command~Command
29
- */
30
- export default class SetHeaderRowCommand extends Command {
31
- /**
32
- * @inheritDoc
33
- */
34
- refresh() {
35
- const model = this.editor.model;
36
- const selectedCells = getSelectionAffectedTableCells( model.document.selection );
37
- const isInTable = selectedCells.length > 0;
38
-
39
- this.isEnabled = isInTable;
40
-
41
- /**
42
- * Flag indicating whether the command is active. The command is active when the
43
- * {@link module:engine/model/selection~Selection} is in a header row.
44
- *
45
- * @observable
46
- * @readonly
47
- * @member {Boolean} #value
48
- */
49
- this.value = isInTable && selectedCells.every( cell => this._isInHeading( cell, cell.parent.parent ) );
50
- }
51
-
52
- /**
53
- * Executes the command.
54
- *
55
- * When the selection is in a non-header row, the command will set the `headingRows` table attribute to cover that row.
56
- *
57
- * When the selection is already in a header row, it will set `headingRows` so the heading section will end before that row.
58
- *
59
- * @fires execute
60
- * @param {Object} options
61
- * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) the header rows according to
62
- * the `forceValue` parameter instead of the current model state.
63
- */
64
- execute( options = {} ) {
65
- if ( options.forceValue === this.value ) {
66
- return;
67
- }
68
- const model = this.editor.model;
69
- const selectedCells = getSelectionAffectedTableCells( model.document.selection );
70
- const table = selectedCells[ 0 ].findAncestor( 'table' );
71
-
72
- const { first, last } = getRowIndexes( selectedCells );
73
- const headingRowsToSet = this.value ? first : last + 1;
74
- const currentHeadingRows = table.getAttribute( 'headingRows' ) || 0;
75
-
76
- model.change( writer => {
77
- if ( headingRowsToSet ) {
78
- // Changing heading rows requires to check if any of a heading cell is overlapping vertically the table head.
79
- // Any table cell that has a rowspan attribute > 1 will not exceed the table head so we need to fix it in rows below.
80
- const startRow = headingRowsToSet > currentHeadingRows ? currentHeadingRows : 0;
81
- const overlappingCells = getVerticallyOverlappingCells( table, headingRowsToSet, startRow );
82
-
83
- for ( const { cell } of overlappingCells ) {
84
- splitHorizontally( cell, headingRowsToSet, writer );
85
- }
86
- }
87
-
88
- updateNumericAttribute( 'headingRows', headingRowsToSet, table, writer, 0 );
89
- } );
90
- }
91
-
92
- /**
93
- * Checks if a table cell is in the heading section.
94
- *
95
- * @param {module:engine/model/element~Element} tableCell
96
- * @param {module:engine/model/element~Element} table
97
- * @returns {Boolean}
98
- * @private
99
- */
100
- _isInHeading( tableCell, table ) {
101
- const headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );
102
-
103
- return !!headingRows && tableCell.parent.index < headingRows;
104
- }
105
- }
1
+ /**
2
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module table/commands/setheaderrowcommand
8
+ */
9
+
10
+ import { Command } from 'ckeditor5/src/core';
11
+
12
+ import { updateNumericAttribute } from '../utils/common';
13
+ import { getRowIndexes, getSelectionAffectedTableCells } from '../utils/selection';
14
+ import { getVerticallyOverlappingCells, splitHorizontally } from '../utils/structure';
15
+
16
+ /**
17
+ * The header row command.
18
+ *
19
+ * The command is registered by {@link module:table/tableediting~TableEditing} as the `'setTableColumnHeader'` editor command.
20
+ *
21
+ * You can make the row containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element) by executing:
22
+ *
23
+ * editor.execute( 'setTableRowHeader' );
24
+ *
25
+ * **Note:** All preceding rows will also become headers. If the current row is already a header, executing this command
26
+ * will make it a regular row back again (including the following rows).
27
+ *
28
+ * @extends module:core/command~Command
29
+ */
30
+ export default class SetHeaderRowCommand extends Command {
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ refresh() {
35
+ const model = this.editor.model;
36
+ const selectedCells = getSelectionAffectedTableCells( model.document.selection );
37
+ const isInTable = selectedCells.length > 0;
38
+
39
+ this.isEnabled = isInTable;
40
+
41
+ /**
42
+ * Flag indicating whether the command is active. The command is active when the
43
+ * {@link module:engine/model/selection~Selection} is in a header row.
44
+ *
45
+ * @observable
46
+ * @readonly
47
+ * @member {Boolean} #value
48
+ */
49
+ this.value = isInTable && selectedCells.every( cell => this._isInHeading( cell, cell.parent.parent ) );
50
+ }
51
+
52
+ /**
53
+ * Executes the command.
54
+ *
55
+ * When the selection is in a non-header row, the command will set the `headingRows` table attribute to cover that row.
56
+ *
57
+ * When the selection is already in a header row, it will set `headingRows` so the heading section will end before that row.
58
+ *
59
+ * @fires execute
60
+ * @param {Object} options
61
+ * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) the header rows according to
62
+ * the `forceValue` parameter instead of the current model state.
63
+ */
64
+ execute( options = {} ) {
65
+ if ( options.forceValue === this.value ) {
66
+ return;
67
+ }
68
+ const model = this.editor.model;
69
+ const selectedCells = getSelectionAffectedTableCells( model.document.selection );
70
+ const table = selectedCells[ 0 ].findAncestor( 'table' );
71
+
72
+ const { first, last } = getRowIndexes( selectedCells );
73
+ const headingRowsToSet = this.value ? first : last + 1; // Only first row, origin is last + 1
74
+ const currentHeadingRows = table.getAttribute( 'headingRows' ) || 0;
75
+
76
+ model.change( writer => {
77
+
78
+ if(headingRowsToSet > 1){
79
+ return;
80
+ }
81
+
82
+ if ( headingRowsToSet ) {
83
+ // Changing heading rows requires to check if any of a heading cell is overlapping vertically the table head.
84
+ // Any table cell that has a rowspan attribute > 1 will not exceed the table head so we need to fix it in rows below.
85
+ const startRow = headingRowsToSet > currentHeadingRows ? currentHeadingRows : 0;
86
+ const overlappingCells = getVerticallyOverlappingCells( table, headingRowsToSet, startRow );
87
+
88
+ for ( const { cell } of overlappingCells ) {
89
+ splitHorizontally( cell, headingRowsToSet, writer );
90
+ }
91
+ }
92
+
93
+ updateNumericAttribute( 'headingRows', headingRowsToSet, table, writer, 0 );
94
+ } );
95
+ }
96
+
97
+ /**
98
+ * Checks if a table cell is in the heading section.
99
+ *
100
+ * @param {module:engine/model/element~Element} tableCell
101
+ * @param {module:engine/model/element~Element} table
102
+ * @returns {Boolean}
103
+ * @private
104
+ */
105
+ _isInHeading( tableCell, table ) {
106
+ const headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );
107
+
108
+ return !!headingRows && tableCell.parent.index < headingRows;
109
+ }
110
+ }