editableelement.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /**
  2. * @license Copyright (c) 2003-2017, 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. * @extends module:engine/view/containerelement~ContainerElement
  18. * @mixes module:utils/observablemixin~ObservaleMixin
  19. */
  20. export default class EditableElement extends ContainerElement {
  21. /**
  22. * Creates an editable element.
  23. */
  24. constructor( name, attrs, children ) {
  25. super( name, attrs, children );
  26. /**
  27. * Whether the editable is in read-write or read-only mode.
  28. *
  29. * @observable
  30. * @member {Boolean} module:engine/view/editableelement~EditableElement#isReadOnly
  31. */
  32. this.set( 'isReadOnly', false );
  33. /**
  34. * Whether the editable is focused.
  35. *
  36. * This property updates when {@link module:engine/view/document~Document#isFocused document.isFocused} is changed and after each
  37. * {@link module:engine/view/document~Document#render render} method call.
  38. *
  39. * @readonly
  40. * @observable
  41. * @member {Boolean} module:engine/view/editableelement~EditableElement#isFocused
  42. */
  43. this.set( 'isFocused', false );
  44. /**
  45. * The {@link module:engine/view/document~Document} which is an owner of this root.
  46. * Can only by set once.
  47. * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-editableelement-document-already-set`
  48. * when document is already set.
  49. *
  50. * @member {module:engine/view/document~Document} #document
  51. */
  52. }
  53. get document() {
  54. return this.getCustomProperty( documentSymbol );
  55. }
  56. set document( document ) {
  57. if ( this.getCustomProperty( documentSymbol ) ) {
  58. /**
  59. * View document is already set. It can only be set once.
  60. *
  61. * @error view-editableelement-document-already-set
  62. */
  63. throw new CKEditorError( 'view-editableelement-document-already-set: View document is already set.' );
  64. }
  65. this.setCustomProperty( documentSymbol, document );
  66. this.bind( 'isFocused' ).to(
  67. document,
  68. 'isFocused',
  69. ( isFocused ) => isFocused && document.selection.editableElement == this
  70. );
  71. // Update focus state after each rendering. Selection might be moved to different editable before rendering,
  72. // but this does not mean that editable has focus - it will be placed there after rendering.
  73. this.listenTo( document, 'render', () => {
  74. this.isFocused = document.isFocused && document.selection.editableElement == this;
  75. }, { priority: 'low' } );
  76. }
  77. }
  78. mix( EditableElement, ObservableMixin );