document.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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/document
  7. */
  8. import DocumentSelection from './documentselection';
  9. import Collection from '@ckeditor/ckeditor5-utils/src/collection';
  10. import mix from '@ckeditor/ckeditor5-utils/src/mix';
  11. import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
  12. /**
  13. * Document class creates an abstract layer over the content editable area, contains a tree of view elements and
  14. * {@link module:engine/view/documentselection~DocumentSelection view selection} associated with this document.
  15. *
  16. * @mixes module:utils/observablemixin~ObservableMixin
  17. */
  18. export default class Document {
  19. /**
  20. * Creates a Document instance.
  21. */
  22. constructor() {
  23. /**
  24. * Selection done on this document.
  25. *
  26. * @readonly
  27. * @member {module:engine/view/documentselection~DocumentSelection} module:engine/view/document~Document#selection
  28. */
  29. this.selection = new DocumentSelection();
  30. /**
  31. * Roots of the view tree. Collection of the {module:engine/view/element~Element view elements}.
  32. *
  33. * View roots are created as a result of binding between {@link module:engine/view/document~Document#roots} and
  34. * {@link module:engine/model/document~Document#roots} and this is handled by
  35. * {@link module:engine/controller/editingcontroller~EditingController}, so to create view root we need to create
  36. * model root using {@link module:engine/model/document~Document#createRoot}.
  37. *
  38. * @readonly
  39. * @member {Collection} module:engine/view/document~Document#roots
  40. */
  41. this.roots = new Collection( { idProperty: 'rootName' } );
  42. /**
  43. * Defines whether document is in read-only mode.
  44. *
  45. * When document is read-ony then all roots are read-only as well and caret placed inside this root is hidden.
  46. *
  47. * @observable
  48. * @member {Boolean} #isReadOnly
  49. */
  50. this.set( 'isReadOnly', false );
  51. /**
  52. * True if document is focused.
  53. *
  54. * This property is updated by the {@link module:engine/view/observer/focusobserver~FocusObserver}.
  55. * If the {@link module:engine/view/observer/focusobserver~FocusObserver} is disabled this property will not change.
  56. *
  57. * @readonly
  58. * @observable
  59. * @member {Boolean} module:engine/view/document~Document#isFocused
  60. */
  61. this.set( 'isFocused', false );
  62. /**
  63. * True if composition is in progress inside the document.
  64. *
  65. * This property is updated by the {@link module:engine/view/observer/compositionobserver~CompositionObserver}.
  66. * If the {@link module:engine/view/observer/compositionobserver~CompositionObserver} is disabled this property will not change.
  67. *
  68. * @readonly
  69. * @observable
  70. * @member {Boolean} module:engine/view/document~Document#isComposing
  71. */
  72. this.set( 'isComposing', false );
  73. /**
  74. * Post-fixer callbacks registered to the view document.
  75. *
  76. * @private
  77. * @member {Set}
  78. */
  79. this._postFixers = new Set();
  80. }
  81. /**
  82. * Gets a {@link module:engine/view/document~Document#roots view root element} with the specified name. If the name is not
  83. * specific "main" root is returned.
  84. *
  85. * @param {String} [name='main'] Name of the root.
  86. * @returns {module:engine/view/rooteditableelement~RootEditableElement|null} The view root element with the specified name
  87. * or null when there is no root of given name.
  88. */
  89. getRoot( name = 'main' ) {
  90. return this.roots.get( name );
  91. }
  92. /**
  93. * Used to register a post-fixer callback. A post-fixers mechanism allows to update view tree just before rendering
  94. * to the DOM.
  95. *
  96. * Post-fixers are fired just after all changes from the outermost change block were applied but
  97. * before the {@link module:engine/view/view~View#event:render render event} is fired. If a post-fixer callback made
  98. * a change, it should return `true`. When this happens, all post-fixers are fired again to check if something else should
  99. * not be fixed in the new document tree state.
  100. *
  101. * View post-fixers are useful when you wants to update view structure whenever it changes, for instance add some classes
  102. * to elements based on the view structure or selection. However, is you need DOM elements to be already updated, use
  103. * {@link module:engine/view/view~View#event:render render event}.
  104. *
  105. * As a parameter, a post-fixer callback receives a {@link module:engine/view/writer~Writer writer} instance connected with the
  106. * executed changes block.
  107. *
  108. * @param {Function} postFixer
  109. */
  110. registerPostFixer( postFixer ) {
  111. this._postFixers.add( postFixer );
  112. }
  113. /**
  114. * Performs post-fixer loops. Executes post-fixer callbacks as long as none of them has done any changes to the model.
  115. *
  116. * @protected
  117. * @param {module:engine/view/writer~Writer} writer
  118. */
  119. _callPostFixers( writer ) {
  120. let wasFixed = false;
  121. do {
  122. for ( const callback of this._postFixers ) {
  123. wasFixed = callback( writer );
  124. if ( wasFixed ) {
  125. break;
  126. }
  127. }
  128. } while ( wasFixed );
  129. }
  130. }
  131. mix( Document, ObservableMixin );
  132. /**
  133. * Enum representing type of the change.
  134. *
  135. * Possible values:
  136. *
  137. * * `children` - for child list changes,
  138. * * `attributes` - for element attributes changes,
  139. * * `text` - for text nodes changes.
  140. *
  141. * @typedef {String} module:engine/view/document~ChangeType
  142. */