1 | /**
|
2 | * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3 | * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4 | */
|
5 | /**
|
6 | * @module list/todolist/checktodolistcommand
|
7 | */
|
8 | import { Command } from 'ckeditor5/src/core';
|
9 | const attributeKey = 'todoListChecked';
|
10 | /**
|
11 | * The check to-do command.
|
12 | *
|
13 | * The command is registered by the {@link module:list/todolist/todolistediting~TodoListEditing} as
|
14 | * the `checkTodoList` editor command and it is also available via aliased `todoListCheck` name.
|
15 | */
|
16 | export default class CheckTodoListCommand extends Command {
|
17 | /**
|
18 | * @inheritDoc
|
19 | */
|
20 | constructor(editor) {
|
21 | super(editor);
|
22 | this._selectedElements = [];
|
23 | // Refresh command before executing to be sure all values are up to date.
|
24 | // It is needed when selection has changed before command execution, in the same change block.
|
25 | this.on('execute', () => {
|
26 | this.refresh();
|
27 | }, { priority: 'highest' });
|
28 | }
|
29 | /**
|
30 | * Updates the command's {@link #value} and {@link #isEnabled} properties based on the current selection.
|
31 | */
|
32 | refresh() {
|
33 | this._selectedElements = this._getSelectedItems();
|
34 | this.value = this._selectedElements.every(element => !!element.getAttribute(attributeKey));
|
35 | this.isEnabled = !!this._selectedElements.length;
|
36 | }
|
37 | /**
|
38 | * Gets all to-do list items selected by the {@link module:engine/model/selection~Selection}.
|
39 | */
|
40 | _getSelectedItems() {
|
41 | const model = this.editor.model;
|
42 | const schema = model.schema;
|
43 | const selectionRange = model.document.selection.getFirstRange();
|
44 | const startElement = selectionRange.start.parent;
|
45 | const elements = [];
|
46 | if (schema.checkAttribute(startElement, attributeKey)) {
|
47 | elements.push(startElement);
|
48 | }
|
49 | for (const item of selectionRange.getItems()) {
|
50 | if (schema.checkAttribute(item, attributeKey) && !elements.includes(item)) {
|
51 | elements.push(item);
|
52 | }
|
53 | }
|
54 | return elements;
|
55 | }
|
56 | /**
|
57 | * Executes the command.
|
58 | *
|
59 | * @param options.forceValue If set, it will force the command behavior. If `true`, the command will apply
|
60 | * the attribute. Otherwise, the command will remove the attribute. If not set, the command will look for its current
|
61 | * value to decide what it should do.
|
62 | */
|
63 | execute(options = {}) {
|
64 | this.editor.model.change(writer => {
|
65 | for (const element of this._selectedElements) {
|
66 | const value = (options.forceValue === undefined) ? !this.value : options.forceValue;
|
67 | if (value) {
|
68 | writer.setAttribute(attributeKey, true, element);
|
69 | }
|
70 | else {
|
71 | writer.removeAttribute(attributeKey, element);
|
72 | }
|
73 | }
|
74 | });
|
75 | }
|
76 | }
|