editableelement.js 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module engine/view/editableelement
  7. */
  8. import ContainerElement from './containerelement';
  9. import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
  10. import mix from '@ckeditor/ckeditor5-utils/src/mix';
  11. import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
  12. const documentSymbol = Symbol( 'document' );
  13. /**
  14. * Editable element which can be a {@link module:engine/view/rooteditableelement~RootEditableElement root}
  15. * or nested editable area in the editor.
  16. *
  17. * Editable is automatically read-only when its {module:engine/view/document~Document Document} is read-only.
  18. *
  19. * @extends module:engine/view/containerelement~ContainerElement
  20. * @mixes module:utils/observablemixin~ObservableMixin
  21. */
  22. export default class EditableElement extends ContainerElement {
  23. /**
  24. * Creates an editable element.
  25. */
  26. constructor( name, attrs, children ) {
  27. super( name, attrs, children );
  28. /**
  29. * Whether the editable is in read-write or read-only mode.
  30. *
  31. * @observable
  32. * @member {Boolean} module:engine/view/editableelement~EditableElement#isReadOnly
  33. */
  34. this.set( 'isReadOnly', false );
  35. /**
  36. * Whether the editable is focused.
  37. *
  38. * This property updates when {@link module:engine/view/document~Document#isFocused document.isFocused} is changed and after each
  39. * {@link module:engine/view/document~Document#render render} method call.
  40. *
  41. * @readonly
  42. * @observable
  43. * @member {Boolean} module:engine/view/editableelement~EditableElement#isFocused
  44. */
  45. this.set( 'isFocused', false );
  46. /**
  47. * The {@link module:engine/view/document~Document} which is an owner of this root.
  48. * Can only by set once.
  49. * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-editableelement-document-already-set`
  50. * when document is already set.
  51. *
  52. * @member {module:engine/view/document~Document} #document
  53. */
  54. }
  55. get document() {
  56. return this.getCustomProperty( documentSymbol );
  57. }
  58. set document( document ) {
  59. if ( this.getCustomProperty( documentSymbol ) ) {
  60. /**
  61. * View document is already set. It can only be set once.
  62. *
  63. * @error view-editableelement-document-already-set
  64. */
  65. throw new CKEditorError( 'view-editableelement-document-already-set: View document is already set.' );
  66. }
  67. this.setCustomProperty( documentSymbol, document );
  68. this.bind( 'isReadOnly' ).to( document );
  69. this.bind( 'isFocused' ).to(
  70. document,
  71. 'isFocused',
  72. isFocused => isFocused && document.selection.editableElement == this
  73. );
  74. // Update focus state before each rendering. Rendering should not change neither the selection nor the value of
  75. // document.isFocused property.
  76. this.listenTo( document, 'render', () => {
  77. this.isFocused = document.isFocused && document.selection.editableElement == this;
  78. }, { priority: 'high' } );
  79. }
  80. }
  81. mix( EditableElement, ObservableMixin );