8
0

alignmentcommand.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module alignment/alignmentcommand
  7. */
  8. import Command from '@ckeditor/ckeditor5-core/src/command';
  9. import first from '@ckeditor/ckeditor5-utils/src/first';
  10. import { isDefault } from './utils';
  11. const ALIGNMENT = 'alignment';
  12. /**
  13. * The alignment command plugin.
  14. *
  15. * @extends module:core/command~Command
  16. */
  17. export default class AlignmentCommand extends Command {
  18. /**
  19. * @inheritDoc
  20. */
  21. refresh() {
  22. const firstBlock = first( this.editor.model.document.selection.getSelectedBlocks() );
  23. // As first check whether to enable or disable the command as the value will always be false if the command cannot be enabled.
  24. this.isEnabled = !!firstBlock && this._canBeAligned( firstBlock );
  25. /**
  26. * A value of the current block's alignment.
  27. *
  28. * @observable
  29. * @readonly
  30. * @member {String} #value
  31. */
  32. this.value = ( this.isEnabled && firstBlock.hasAttribute( 'alignment' ) ) ? firstBlock.getAttribute( 'alignment' ) : 'left';
  33. }
  34. /**
  35. * Executes the command. Applies the alignment `value` to the selected blocks.
  36. * If no `value` is passed, is a default one or is equal to currently selected block's alignment attribute,
  37. * it will remove the attribute from the selected blocks.
  38. *
  39. * @param {Object} [options] Options for the executed command.
  40. * @param {String} [options.value] The value to apply.
  41. * @fires execute
  42. */
  43. execute( options = {} ) {
  44. const editor = this.editor;
  45. const model = editor.model;
  46. const doc = model.document;
  47. const value = options.value;
  48. model.change( writer => {
  49. // Get only those blocks from selected that can have alignment set
  50. const blocks = Array.from( doc.selection.getSelectedBlocks() ).filter( block => this._canBeAligned( block ) );
  51. const currentAlignment = blocks[ 0 ].getAttribute( 'alignment' );
  52. // Remove alignment attribute if current alignment is:
  53. // - default (should not be stored in model as it will bloat model data)
  54. // - equal to currently set
  55. // - or no value is passed - denotes default alignment.
  56. const removeAlignment = isDefault( value ) || currentAlignment === value || !value;
  57. if ( removeAlignment ) {
  58. removeAlignmentFromSelection( blocks, writer );
  59. } else {
  60. setAlignmentOnSelection( blocks, writer, value );
  61. }
  62. } );
  63. }
  64. /**
  65. * Checks whether a block can have alignment set.
  66. *
  67. * @private
  68. * @param {module:engine/model/element~Element} block A block to be checked.
  69. * @returns {Boolean}
  70. */
  71. _canBeAligned( block ) {
  72. return this.editor.model.schema.checkAttribute( block, ALIGNMENT );
  73. }
  74. }
  75. // Removes alignment attribute from blocks.
  76. // @private
  77. function removeAlignmentFromSelection( blocks, writer ) {
  78. for ( const block of blocks ) {
  79. writer.removeAttribute( ALIGNMENT, block );
  80. }
  81. }
  82. // Sets alignment attribute on blocks.
  83. // @private
  84. function setAlignmentOnSelection( blocks, writer, alignment ) {
  85. for ( const block of blocks ) {
  86. writer.setAttribute( ALIGNMENT, alignment, block );
  87. }
  88. }