nodelist.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. CKEDITOR.define( [
  7. 'treemodel/character',
  8. 'treemodel/text',
  9. 'treemodel/node',
  10. 'utils'
  11. ], ( Character, Text, Node, utils ) => {
  12. /**
  13. * List of nodes. It is used to represent multiple nodes with a given order, for example children of
  14. * {@link treeModel.Element} object or nodes inserted using {@link treeModel.operation.InsertOperation}.
  15. *
  16. * Thanks to the constructor, which accepts various arguments, this class lets you easily create desired list of nodes.
  17. *
  18. * It also may internally compress nodes.
  19. *
  20. * @class treeModel.NodeList
  21. */
  22. class NodeList {
  23. /**
  24. * Constructor let you create a list of nodes in many ways. See examples:
  25. *
  26. * let nodeList = new NodeList( [ new Element( p1 ), new Element( p1 ) ] );
  27. * nodeList.length; // 2
  28. *
  29. * let nodeList = new NodeList( new Element( p ) );
  30. * nodeList.length; // 1
  31. *
  32. * let nodeList = new NodeList( [ 'foo', new Element( p ), 'bar' ] );
  33. * nodeList.length; // 7
  34. *
  35. * let nodeList = new NodeList( 'foo' );
  36. * nodeList.length; // 3
  37. *
  38. * let nodeList = new NodeList( new Text( 'foo', [ new Attribute( 'bar', 'bom' ) ] ) );
  39. * nodeList.length; // 3
  40. * nodeList.get( 0 ).getAttr( 'bar' ); // 'bom'
  41. * nodeList.get( 1 ).getAttr( 'bar' ); // 'bom'
  42. * nodeList.get( 2 ).getAttr( 'bar' ); // 'bom'
  43. *
  44. * let nodeListA = new NodeList( 'foo' );
  45. * let nodeListB = new NodeList( nodeListA );
  46. * nodeListA === nodeListB // true
  47. * nodeListB.length // 3
  48. *
  49. * @param {treeModel.Node|treeModel.Text|treeModel.NodeList|String|Iterable} nodes List of nodes.
  50. * @constructor
  51. */
  52. constructor( nodes ) {
  53. if ( nodes instanceof NodeList ) {
  54. // We do not clone anything.
  55. return nodes;
  56. }
  57. /**
  58. * Internal array to store nodes.
  59. *
  60. * @private
  61. * @property {Array}
  62. */
  63. this._nodes = [];
  64. if ( nodes ) {
  65. let node, character;
  66. if ( !utils.isIterable( nodes ) ) {
  67. nodes = [ nodes ];
  68. }
  69. for ( node of nodes ) {
  70. // Node.
  71. if ( node instanceof Node ) {
  72. this._nodes.push( node );
  73. }
  74. // Text.
  75. else if ( node instanceof Text ) {
  76. for ( character of node.text ) {
  77. this._nodes.push( new Character( character, node.attrs ) );
  78. }
  79. }
  80. // String.
  81. else {
  82. for ( character of node ) {
  83. this._nodes.push( new Character( character ) );
  84. }
  85. }
  86. }
  87. }
  88. }
  89. /**
  90. * Number of nodes in the node list.
  91. *
  92. * @readonly
  93. * @property {Number} length
  94. */
  95. get length() {
  96. return this._nodes.length;
  97. }
  98. /**
  99. * Node list iterator.
  100. */
  101. [ Symbol.iterator ]() {
  102. return this._nodes[ Symbol.iterator ]();
  103. }
  104. /**
  105. * Returns node at the given index.
  106. *
  107. * @param {Number} index Node index.
  108. * @returns {treeModel.Node} Node at given index.
  109. */
  110. get( index ) {
  111. return this._nodes[ index ];
  112. }
  113. /**
  114. * Search for the node in the node list.
  115. *
  116. * @param {treeModel.Node} node Node to find.
  117. * @returns {Number} Position of the node in the list.
  118. */
  119. indexOf( node ) {
  120. return this._nodes.indexOf( node );
  121. }
  122. /**
  123. * Inserts nodes from the given node list into this node list at the given index.
  124. *
  125. * @param {Number} index Position where nodes should be inserted.
  126. * @param {treeModel.NodeList} nodeList List of nodes to insert.
  127. */
  128. insert( index, nodeList ) {
  129. this._nodes.splice.apply( this._nodes, [ index, 0 ].concat( nodeList._nodes ) );
  130. }
  131. /**
  132. * Removes number of nodes starting at the given index.
  133. *
  134. * @param {Number} index Position of the first node to remove.
  135. * @param {Number} number Number of nodes to remove.
  136. * @returns {treeModel.NodeList} List of removed nodes.
  137. */
  138. remove( index, number ) {
  139. return new NodeList( this._nodes.splice( index, number ) );
  140. }
  141. }
  142. return NodeList;
  143. } );