8
0

position.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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( [ 'utils' ], function( utils ) {
  7. /**
  8. * Position is always before of after a node.
  9. * See {@link #path} property for more information.
  10. *
  11. * @class document.Position
  12. */
  13. class Position {
  14. /**
  15. * Creates a position.
  16. *
  17. * @param {Array} path Position path. See {@link #path} property for more information.
  18. * @param {document.Document} document Document which position refers to.
  19. */
  20. constructor( path, document ) {
  21. /**
  22. * Position of the node it the tree. For example:
  23. *
  24. * root
  25. * |- p Before: [ 0 ] After: [ 1 ]
  26. * |- ul Before: [ 1 ] After: [ 2 ]
  27. * |- li Before: [ 1, 0 ] After: [ 1, 1 ]
  28. * | |- f Before: [ 1, 0, 0 ] After: [ 1, 0, 1 ]
  29. * | |- o Before: [ 1, 0, 1 ] After: [ 1, 0, 2 ]
  30. * | |- o Before: [ 1, 0, 2 ] After: [ 1, 0, 3 ]
  31. * |- li Before: [ 1, 1 ] After: [ 1, 2 ]
  32. * |- b Before: [ 1, 1, 0 ] After: [ 1, 1, 1 ]
  33. * |- a Before: [ 1, 1, 1 ] After: [ 1, 1, 2 ]
  34. * |- r Before: [ 1, 1, 2 ] After: [ 1, 1, 3 ]
  35. *
  36. * @type {Array}
  37. */
  38. this.path = path;
  39. /**
  40. * Document which position refers to.
  41. *
  42. * @type {document.Document}
  43. */
  44. this.document = document;
  45. }
  46. /**
  47. * Create position from the parent element and the offset in that element.
  48. *
  49. * @param {document.Element} parent Position parent element.
  50. * @param {Number} offset Position offset.
  51. * @param {document.Document} document Document which position refers to.
  52. */
  53. static makePositionFromParentAndOffset( parent, offset, document ) {
  54. var path = parent.getPath();
  55. path.push( offset );
  56. return new Position( path, document );
  57. }
  58. /**
  59. * Set the position before given node.
  60. *
  61. * @param {document.node} node Node the position should be directly before.
  62. * @param {document.Document} document Document which position refers to.
  63. */
  64. static makePositionBefore( node, document ) {
  65. if ( !node.parent ) {
  66. throw 'You can not make position before root.';
  67. }
  68. return Position.makePositionFromParentAndOffset( node.parent, node.positionInParent, document );
  69. }
  70. /**
  71. * Set the position after given node.
  72. *
  73. * @param {document.node} node Node the position should be directly after.
  74. * @param {document.Document} document Document which position refers to.
  75. */
  76. static makePositionAfter( node, document ) {
  77. if ( !node.parent ) {
  78. throw 'You can not make position after root.';
  79. }
  80. return Position.makePositionFromParentAndOffset( node.parent, node.positionInParent + 1, document );
  81. }
  82. /**
  83. * Element which is a parent of the position.
  84. *
  85. * @readonly
  86. * @property {document.Element} parent
  87. */
  88. get parent() {
  89. var parent = this.document.root;
  90. var i, len;
  91. for ( i = 0, len = this.path.length - 1; i < len; i++ ) {
  92. parent = parent.children[ this.path[ i ] ];
  93. }
  94. return parent;
  95. }
  96. /**
  97. * Position offset in the parent, which is the last element of the path.
  98. *
  99. * @readonly
  100. * @property {Number} offset
  101. */
  102. get offset() {
  103. return utils.last( this.path );
  104. }
  105. /**
  106. * Node directly before the position.
  107. *
  108. * @readonly
  109. * @type {Node}
  110. */
  111. get nodeBefore() {
  112. return this.parent.children[ this.offset - 1 ] || null;
  113. }
  114. /**
  115. * Node directly after the position.
  116. *
  117. * @readonly
  118. * @type {Node}
  119. */
  120. get nodeAfter() {
  121. return this.parent.children[ this.offset ] || null;
  122. }
  123. /**
  124. * Two positions equals if paths equal.
  125. *
  126. * @param {document.Position} otherPosition Position to compare.
  127. * @returns {Boolean} true if positions equal.
  128. */
  129. isEqual( otherPosition ) {
  130. return utils.isEqual( this.path, otherPosition.path );
  131. }
  132. }
  133. return Position;
  134. } );