8
0

positioniterator.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. 'document/character',
  8. 'document/element',
  9. 'document/position'
  10. ], function( Character, Element, Position ) {
  11. var OPENING_TAG = 0;
  12. var CLOSING_TAG = 1;
  13. var CHARACTER = 2;
  14. /**
  15. * Range iterator class.
  16. *
  17. * @class document.Range
  18. */
  19. class PositionIterator {
  20. /**
  21. * Create a range iterator.
  22. *
  23. * @param {document.range} boundaries Range to define boundaries of the iterator.
  24. */
  25. constructor( boundaries, iteratorPosition ) {
  26. /**
  27. * Start position.
  28. *
  29. * @type {document.Position}
  30. */
  31. if ( boundaries instanceof Position ) {
  32. this.position = boundaries;
  33. } else {
  34. this.boundaries = boundaries;
  35. this.position = iteratorPosition || boundaries.start;
  36. }
  37. }
  38. next() {
  39. var position = this.position;
  40. // We are at the end of the root.
  41. if ( position.parent.parent === null && position.offset === position.parent.children.length ) {
  42. return { done: true };
  43. }
  44. if ( this.boundaries && position.equals( this.boundaries.end ) ) {
  45. return { done: true };
  46. }
  47. var nodeAfter = position.nodeAfter;
  48. if ( nodeAfter instanceof Element ) {
  49. this.position = new Position( nodeAfter, 0 );
  50. return formatReturnValue( OPENING_TAG, nodeAfter );
  51. } else if ( nodeAfter instanceof Character ) {
  52. this.position = new Position( position.parent, position.offset + 1 );
  53. return formatReturnValue( CHARACTER, nodeAfter );
  54. } else {
  55. this.position = new Position( position.parent.parent, position.parent.positionInParent + 1 );
  56. return formatReturnValue( CLOSING_TAG, this.position.nodeBefore );
  57. }
  58. }
  59. previous() {
  60. var position = this.position;
  61. // We are at the begging of the root.
  62. if ( position.parent.parent === null && position.offset === 0 ) {
  63. return { done: true };
  64. }
  65. if ( this.boundaries && position.equals( this.boundaries.start ) ) {
  66. return { done: true };
  67. }
  68. var nodeBefore = position.nodeBefore;
  69. if ( nodeBefore instanceof Element ) {
  70. this.position = new Position( nodeBefore, nodeBefore.children.length );
  71. return formatReturnValue( CLOSING_TAG, nodeBefore );
  72. } else if ( nodeBefore instanceof Character ) {
  73. this.position = new Position( position.parent, position.offset - 1 );
  74. return formatReturnValue( CHARACTER, nodeBefore );
  75. } else {
  76. this.position = new Position( position.parent.parent, position.parent.positionInParent );
  77. return formatReturnValue( OPENING_TAG, this.position.nodeAfter );
  78. }
  79. }
  80. }
  81. function formatReturnValue( type, node ) {
  82. return {
  83. done: false,
  84. value: {
  85. type: type,
  86. node: node
  87. }
  88. };
  89. }
  90. /**
  91. * Flag for linear data opening tag.
  92. *
  93. * @readonly
  94. */
  95. PositionIterator.OPENING_TAG = OPENING_TAG;
  96. /**
  97. * Flag for linear data closing tag.
  98. *
  99. * @readonly
  100. */
  101. PositionIterator.CLOSING_TAG = CLOSING_TAG;
  102. /**
  103. * Flag for linear data character.
  104. *
  105. * @readonly
  106. */
  107. PositionIterator.CHARACTER = CHARACTER;
  108. return PositionIterator;
  109. } );