todolistcheckcommand.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /**
  2. * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /**
  6. * @module list/todolistcheckedcommand
  7. */
  8. import Command from '@ckeditor/ckeditor5-core/src/command';
  9. const attributeKey = 'todoListChecked';
  10. /**
  11. * @extends module:core/command~Command
  12. */
  13. export default class TodoListCheckCommand extends Command {
  14. /**
  15. * @inheritDoc
  16. */
  17. constructor( editor ) {
  18. super( editor );
  19. /**
  20. * Flag indicating whether the command is active. The command is active when at least one of
  21. * {@link module:engine/model/selection~Selection selected} elements is a to-do list item.
  22. *
  23. * @observable
  24. * @readonly
  25. * @member {Boolean} #isEnabled
  26. */
  27. /**
  28. * A List of to-do list item selected by the {@link module:engine/model/selection~Selection}.
  29. *
  30. * @observable
  31. * @readonly
  32. * @member {Array.<module:engine/model/element~Element>} #value
  33. */
  34. /**
  35. * List of to-do list items selected by the {@link module:engine/model/selection~Selection}.
  36. *
  37. * @protected
  38. * @type {Array.<module:engine/model/element~Element>}
  39. */
  40. this._selectedElements = [];
  41. // Refresh command before executing to be sure all values are up to date.
  42. // It is needed when selection has changed before command execution, in the same change block.
  43. this.on( 'execute', () => {
  44. this.refresh();
  45. }, { priority: 'highest' } );
  46. }
  47. /**
  48. * Updates the command's {@link #value} and {@link #isEnabled} based on the current selection.
  49. */
  50. refresh() {
  51. this._selectedElements = this._getSelectedItems();
  52. this.value = this._selectedElements.every( element => !!element.getAttribute( 'todoListChecked' ) );
  53. this.isEnabled = !!this._selectedElements.length;
  54. }
  55. /**
  56. * Gets all to-do list items selected by the {@link module:engine/model/selection~Selection}.
  57. *
  58. * @private
  59. * @returns {Array.<module:engine/model/element~Element>}
  60. */
  61. _getSelectedItems() {
  62. const model = this.editor.model;
  63. const schema = model.schema;
  64. const selectionRange = model.document.selection.getFirstRange();
  65. const startElement = selectionRange.start.parent;
  66. const elements = [];
  67. if ( schema.checkAttribute( startElement, attributeKey ) ) {
  68. elements.push( startElement );
  69. }
  70. for ( const item of selectionRange.getItems() ) {
  71. if ( schema.checkAttribute( item, attributeKey ) && !elements.includes( item ) ) {
  72. elements.push( item );
  73. }
  74. }
  75. return elements;
  76. }
  77. /**
  78. * @inheritDoc
  79. */
  80. execute() {
  81. this.editor.model.change( writer => {
  82. for ( const element of this._selectedElements ) {
  83. if ( !this.value ) {
  84. writer.setAttribute( attributeKey, true, element );
  85. } else {
  86. writer.removeAttribute( attributeKey, element );
  87. }
  88. }
  89. } );
  90. }
  91. }