bookmark.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /**
  2. * @fileOverview
  3. * 선택된 영역을 북마크하여
  4. * 포커스된 document가 변경되거나 DOM 조작을 하더라도 선택 영역이 유지되도록 한다.
  5. * Processor 에서 주로 사용된다.
  6. */
  7. /**
  8. * 선택된 영역을 북마크하여 <br/>
  9. * 포커스된 document가 변경되거나 DOM 조작을 하더라도 선택 영역이 유지되도록 하는 객체로 <br/>
  10. * native range 객체에 있는 5가지 프로퍼티만 저장한다. <br/>
  11. * 주로 Processor와 연관된 객체에서 호출하며, <br/>
  12. * processor.getBookmark()를 통해서 bookmark를 얻어서 사용한다.<br/>
  13. *
  14. * @class
  15. */
  16. Trex.Canvas.Bookmark = Trex.Class.create(/** @lends Trex.Canvas.Bookmark.prototype */{
  17. startContainer: _NULL,
  18. startOffset: 0,
  19. endContainer: _NULL,
  20. endOffset: 0,
  21. initialize: function(processor) {
  22. this.processor = processor;
  23. this.win = processor.win;
  24. this.doc = processor.doc;
  25. this.dummy = function() {
  26. return processor.newDummy();
  27. };
  28. },
  29. /**
  30. * 시작위치와 끝위치를 동일하게 북마크를 수정한다.
  31. * @param {Boolean} toStart - 위치, 시작 = true
  32. * @example
  33. * bookmark.collapse(true);
  34. */
  35. collapse: function (toStart) {
  36. if (toStart) {
  37. this.updateEnd(this.startContainer, this.startOffset);
  38. } else {
  39. this.updateStart(this.endContainer, this.endOffset);
  40. }
  41. },
  42. /**
  43. * native range 객체로 북마크를 수정한다.
  44. * @param {Object} rng - native range 객체
  45. * @example
  46. * bookmark.save(range);
  47. */
  48. save: function(rng) {
  49. this.updateStart(rng.startContainer, rng.startOffset);
  50. this.updateEnd(rng.endContainer, rng.endOffset);
  51. },
  52. /**
  53. * 특정 노드의 앞과 뒤로 북마크를 수정한다.
  54. * @param {Element} node - 특정 노드
  55. * @example
  56. * bookmark.saveAroundNode(node);
  57. */
  58. saveAroundNode: function (node) {
  59. this.updateStartBefore($tom.top(node));
  60. this.updateEndAfter($tom.bottom(node));
  61. },
  62. /**
  63. * 특정 노드의 처음으로 북마크를 수정한다.
  64. * @param {Element} node - 특정 노드
  65. * @example
  66. * bookmark.saveIntoFirst(node);
  67. */
  68. saveIntoFirst: function(node) {
  69. var _node = $tom.top(node);
  70. this.updateEndBefore(_node);
  71. this.collapse(_FALSE);
  72. },
  73. /**
  74. * 특정 노드의 마지막으로 북마크를 수정한다.
  75. * @param {Element} node - 특정 노드
  76. * @example
  77. * bookmark.saveIntoLast(node);
  78. */
  79. saveIntoLast: function(node) {
  80. var _node = $tom.bottom(node);
  81. this.updateEndBefore(_node);
  82. this.collapse(_FALSE);
  83. },
  84. /**
  85. * 특정 노드의 이전으로 북마크를 수정한다.
  86. * @param {Element} node - 특정 노드
  87. * @example
  88. * bookmark.saveNextTo(node);
  89. */
  90. savePreviousTo: function(node) {
  91. if($tom.previous(node)) {
  92. var _node = $tom.top($tom.previous(node));
  93. this.updateEndAfter(_node);
  94. } else {
  95. this.updateEndBefore(node);
  96. }
  97. this.collapse(_FALSE);
  98. },
  99. /**
  100. * 특정 노드의 다음으로 북마크를 수정한다.
  101. * @param {Element} node - 특정 노드
  102. * @example
  103. * bookmark.saveNextTo(node);
  104. */
  105. saveNextTo: function(node) {
  106. if($tom.next(node)) {
  107. var _node = $tom.top($tom.next(node));
  108. this.updateEndBefore(_node);
  109. } else {
  110. this.updateEndAfter(node);
  111. }
  112. this.collapse(_FALSE);
  113. },
  114. /**
  115. * marker node로 북마크를 수정한다.
  116. * @param {Object} marker - marker 객체
  117. * @example
  118. * bookmark.saveWithMarker(marker);
  119. */
  120. saveWithMarker: function(marker) {
  121. if (marker.checkCollapsed()) { //collapsed
  122. this.updateEndAfter(marker.endMarker);
  123. this.collapse(_FALSE);
  124. } else {
  125. this.updateStartBefore(marker.startMarker);
  126. this.updateEndAfter(marker.endMarker);
  127. }
  128. },
  129. /**
  130. * txSelection가지고 저장된 북마크를 선택한다.
  131. * @param {Object} txSelection - txSelection 객체
  132. * @example
  133. * bookmark.select(txSelection);
  134. */
  135. select: function(txSel) {
  136. if (this.isValid()) {
  137. var _rng = txSel.createTextRange();
  138. try {
  139. txSel.setStart(_rng, this.startContainer, this.startOffset);
  140. txSel.setEnd(_rng, this.endContainer, this.endOffset);
  141. } catch (e) {
  142. console.log(e)
  143. }
  144. txSel.selectRange(_rng);
  145. }
  146. this.reset();
  147. },
  148. isValid: function() {
  149. return this.isValidStartContainer() && this.isValidEndContainer();
  150. },
  151. isValidStartContainer: function() {
  152. return this.doc.body === $tom.body(this.startContainer);
  153. },
  154. isValidEndContainer: function() {
  155. return this.doc.body === $tom.body(this.endContainer);
  156. },
  157. /**
  158. * @private
  159. * 시작 관련 프로퍼티를 특정 위치로 지정한다.
  160. * @param {Element} node - 특정 부모 노드
  161. * @param {Number} offset - 노드의 옵셋
  162. * @example
  163. * bookmark.updateStart(node, 1);
  164. */
  165. updateStart: function(node, offset) {
  166. this.startContainer = node;
  167. this.startOffset = offset;
  168. },
  169. /**
  170. * @private
  171. * 시작 관련 프로퍼티를 특정 위치로 이전으로 지정한다.
  172. * @param {Element} node - 특정 노드
  173. * @example
  174. * bookmark.updateStartBefore(node);
  175. */
  176. updateStartBefore: function(node) {
  177. var _tNode = this.dummy();
  178. $tom.insertAt(_tNode, node);
  179. this.startContainer = _tNode;
  180. this.startOffset = 0;
  181. },
  182. /**
  183. * @private
  184. * 시작 관련 프로퍼티를 특정 위치로 다음으로 지정한다.
  185. * @param {Element} node - 특정 노드
  186. * @example
  187. * bookmark.updateStartAfter(node);
  188. */
  189. updateStartAfter: function(node) {
  190. var _tNode = this.dummy();
  191. $tom.insertNext(_tNode, node);
  192. this.startContainer = _tNode;
  193. this.startOffset = 0;
  194. },
  195. /**
  196. * @private
  197. * 끝 관련 프로퍼티를 특정 위치로 지정한다.
  198. * @param {Element} node - 특정 부모 노드
  199. * @param {Number} offset - 노드의 옵셋
  200. * @example
  201. * bookmark.updateEnd(node, 1);
  202. */
  203. updateEnd: function(node, offset) {
  204. this.endContainer = node;
  205. this.endOffset = offset;
  206. },
  207. /**
  208. * @private
  209. * 끝 관련 프로퍼티를 특정 위치로 이전으로 지정한다.
  210. * @param {Element} node - 특정 노드
  211. * @example
  212. * bookmark.updateEndBefore(node);
  213. */
  214. updateEndBefore: function(node) {
  215. var _tNode = this.dummy();
  216. if (node.nodeName && node.nodeName.toUpperCase() == "P" && !node.nodeValue) { // Note: 마지막 조건( !node.nodeValue)은 무의미한데..
  217. $tom.append(node, _tNode);
  218. }else {
  219. $tom.insertAt(_tNode, node);
  220. }
  221. this.endContainer = _tNode;
  222. this.endOffset = _tNode.length;
  223. },
  224. /**
  225. * @private
  226. * 끝 관련 프로퍼티를 특정 위치로 다음으로 지정한다.
  227. * @param {Element} node - 특정 노드
  228. * @example
  229. * bookmark.updateEndAfter(node);
  230. */
  231. updateEndAfter: function(node) {
  232. var _tNode = this.dummy();
  233. $tom.insertNext(_tNode, node);
  234. this.endContainer = _tNode;
  235. this.endOffset = _tNode.length;
  236. },
  237. /**
  238. * @private
  239. * 북마크를 초기화한다.
  240. * @returns {Boolean} - collapse 여부
  241. * @example
  242. * bookmark.reset();
  243. */
  244. reset: function() {
  245. this.startContainer = _NULL;
  246. this.startOffset = 0;
  247. this.endContainer = _NULL;
  248. this.endOffset = 0;
  249. }
  250. });