-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
todolistcheckcommand.js
118 lines (102 loc) · 3.34 KB
/
todolistcheckcommand.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
/**
* @module list/todolistcheckedcommand
*/
import Command from '@ckeditor/ckeditor5-core/src/command';
const attributeKey = 'todoListChecked';
/**
* The to-do check command.
*
* The command is registered by the {@link module:list/todolistediting~TodoListEditing} as
* the `'todoListCheck'` editor command.
*
* @extends module:core/command~Command
*/
export default class TodoListCheckCommand extends Command {
/**
* @inheritDoc
*/
constructor( editor ) {
super( editor );
/**
* A flag indicating whether the command is active. The command is active when at least one of
* {@link module:engine/model/selection~Selection selected} elements is a to-do list item.
*
* @observable
* @readonly
* @member {Boolean} #isEnabled
*/
/**
* A list of to-do list items selected by the {@link module:engine/model/selection~Selection}.
*
* @observable
* @readonly
* @member {Array.<module:engine/model/element~Element>} #value
*/
/**
* A list of to-do list items selected by the {@link module:engine/model/selection~Selection}.
*
* @protected
* @type {Array.<module:engine/model/element~Element>}
*/
this._selectedElements = [];
// Refresh command before executing to be sure all values are up to date.
// It is needed when selection has changed before command execution, in the same change block.
this.on( 'execute', () => {
this.refresh();
}, { priority: 'highest' } );
}
/**
* Updates the command's {@link #value} and {@link #isEnabled} properties based on the current selection.
*/
refresh() {
this._selectedElements = this._getSelectedItems();
this.value = this._selectedElements.every( element => !!element.getAttribute( 'todoListChecked' ) );
this.isEnabled = !!this._selectedElements.length;
}
/**
* Gets all to-do list items selected by the {@link module:engine/model/selection~Selection}.
*
* @private
* @returns {Array.<module:engine/model/element~Element>}
*/
_getSelectedItems() {
const model = this.editor.model;
const schema = model.schema;
const selectionRange = model.document.selection.getFirstRange();
const startElement = selectionRange.start.parent;
const elements = [];
if ( schema.checkAttribute( startElement, attributeKey ) ) {
elements.push( startElement );
}
for ( const item of selectionRange.getItems() ) {
if ( schema.checkAttribute( item, attributeKey ) && !elements.includes( item ) ) {
elements.push( item );
}
}
return elements;
}
/**
* Executes the command.
*
* @param {Object} [options]
* @param {Boolean} [options.forceValue] If set, it will force the command behavior. If `true`, the command will apply
* the attribute. Otherwise, the command will remove the attribute. If not set, the command will look for its current
* value to decide what it should do.
*/
execute( options = {} ) {
this.editor.model.change( writer => {
for ( const element of this._selectedElements ) {
const value = ( options.forceValue === undefined ) ? !this.value : options.forceValue;
if ( value ) {
writer.setAttribute( attributeKey, true, element );
} else {
writer.removeAttribute( attributeKey, element );
}
}
} );
}
}