selection.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. /**
  2. * @fileOverview
  3. * native selection, range 객체를 wrapping 한 객체로 Processor 에서 주로 사용된다.
  4. */
  5. Trex.I.Selection = {};
  6. Trex.I.Selection.Standard = /** @lends Trex.Canvas.Selection.prototype */{
  7. /**
  8. * native selection object를 리턴한다.
  9. * @returns {Object} - native selection object
  10. * @example
  11. * txSelection.getSel();
  12. */
  13. getSel: function(){
  14. return this.win.getSelection();
  15. },
  16. /**
  17. * 선택된 영역의 텍스트 데이터를 리턴한다.
  18. * @returns {String} - 선택된 영역의 텍스트 데이터
  19. * @example
  20. * txSelection.getText();
  21. */
  22. getText: function() {
  23. return this.getSel().toString();
  24. },
  25. /**
  26. * 선택된 영역의 노드를 리턴한다.
  27. * @returns {Element} - 선택된 영역의 노드
  28. * @example
  29. * txSelection.getNode();
  30. */
  31. getNode: function() {
  32. var _rng = this.getRange();
  33. if (_rng) {
  34. var _startContainer = _rng.startContainer;
  35. if (_startContainer.nodeType == 1) {
  36. if ($tom.isBody(_startContainer)) {
  37. return (_startContainer);
  38. } else {
  39. return (_startContainer.childNodes[_rng.startOffset]);
  40. }
  41. } else {
  42. return (_startContainer.parentNode);
  43. }
  44. } else {
  45. return _NULL;
  46. }
  47. },
  48. /**
  49. * native range 를 생성한다.
  50. * @returns {Object} - native range 객체
  51. * @example
  52. * txSelection.createRange();
  53. */
  54. createRange: function() {
  55. return this.doc.createRange();
  56. },
  57. /**
  58. * native text range 를 생성한다.
  59. * @returns {Object} - native text range 객체
  60. * @example
  61. * txSelection.createTextRange();
  62. */
  63. createTextRange: function() {
  64. return this.doc.createRange();
  65. },
  66. /**
  67. * native range object를 리턴한다.
  68. * @returns {Object} - native range 객체
  69. * @example
  70. * txSelection.getRange();
  71. */
  72. getRange: function(collapse) {
  73. var _sel = this.getSel();
  74. if (_sel && _sel.rangeCount > 0) {
  75. if (collapse == _NULL) {
  76. if (_sel.rangeCount == 1) { //단일 Range = 일반적인 경우
  77. return _sel.getRangeAt(0);
  78. } else { //복수 Range -> 단일 Range로 변환
  79. return this.mergeRange(_sel);
  80. }
  81. } else { //Range를 collapse할 경우
  82. var _rng = _sel.getRangeAt(0);
  83. _rng.collapse(collapse);
  84. return _rng;
  85. }
  86. } else { //Range가 없을 경우
  87. return this.doc.createRange();
  88. }
  89. },
  90. /**
  91. * 선택된 영역의 collapse 여부(선택된 영역이 있는지 여부)를 리턴한다.
  92. * @returns {Boolean} - collapse 여부
  93. * @example
  94. * txSelection.isCollapsed();
  95. */
  96. isCollapsed: function() {
  97. var _sel = this.getSel();
  98. return (_sel && _sel.isCollapsed);
  99. },
  100. /**
  101. * 선택된 영역을 collapse 시킨다.
  102. * @param {Boolean} toStart - 위치, 시작 = true
  103. * @example
  104. * txSelection.collapse(true);
  105. */
  106. collapse: function(toStart) {
  107. var _sel = this.getSel();
  108. if (_sel && _sel.rangeCount > 0) {
  109. var _rng = _sel.getRangeAt(0);
  110. _rng.collapse(toStart);
  111. }
  112. },
  113. /**
  114. * 선택된 영역의 컨트롤 노드(img,object,hr,table,button)를 리턴한다.
  115. * @returns {Element} - 선택된 영역의 노드
  116. * @example
  117. * txSelection.getControl();
  118. */
  119. getControl: function() {
  120. var _sel = this.getSel();
  121. var _node;
  122. if ($tx.opera) {
  123. /* @opera IMG 선택시 isCollapsed 가 true 되는 문제가 있음. */
  124. _node = _sel.anchorNode.childNodes[_sel.anchorOffset];
  125. if (_node == _NULL) {
  126. return _NULL;
  127. }
  128. if(_sel.isCollapsed && _node.tagName != "IMG") {
  129. return _NULL;
  130. }
  131. }
  132. else {
  133. if(_sel.isCollapsed) {
  134. return _NULL;
  135. }
  136. _node = _sel.anchorNode.childNodes[_sel.anchorOffset];
  137. }
  138. if($tom.kindOf(_node, '%control')) {
  139. return _node;
  140. } else {
  141. return _NULL;
  142. }
  143. },
  144. /**
  145. * 선택된 영역이 컨트롤 노드인지 여부를 리턴한다.
  146. * @returns {Boolean} - 컨트롤 노드인지 여부
  147. * @example
  148. * txSelection.hasControl();
  149. */
  150. hasControl: function() {
  151. return (this.getControl() != _NULL);
  152. },
  153. /**
  154. * 컨트롤 노드를 선택한다.
  155. * @param {Element} node - 컨트롤 노트
  156. * @example
  157. * txSelection.selectControl(node);
  158. */
  159. selectControl: function(node) {
  160. var _rng = this.createRange();
  161. _rng.selectNode(node);
  162. var _sel = this.getSel();
  163. _sel.removeAllRanges();
  164. _sel.addRange(_rng);
  165. },
  166. /**
  167. * 선택된 영역이 텍스트 데이터 영역의 어떤 위치인지를 리턴한다.
  168. * @returns {Number} - 텍스트 데이터 영역의 어떤 위치인지 <br/>
  169. * 빈 텍스트일 경우 : $tom.__POSITION.__EMPTY_TEXT : -2<br/>
  170. * 텍스트의 처음 : $tom.__POSITION.__START_OF_TEXT : -1<br/>
  171. * 텍스트의 중간 : $tom.__POSITION.__MIDDLE_OF_TEXT : 0<br/>
  172. * 텍스트의 마지막 : $tom.__POSITION.__END_OF_TEXT : 1
  173. * @example
  174. * txSelection.compareTextPos();
  175. */
  176. compareTextPos: function() {
  177. var _rng = this.getRange();
  178. if (_rng) {
  179. var _startContainer = _rng.startContainer;
  180. if (_startContainer.nodeType == 3) {
  181. if ( _startContainer.textContent.trim().length == 0 ){
  182. return $tom.__POSITION.__EMPTY_TEXT;
  183. }else if(_rng.startOffset == 0 ) {
  184. return $tom.__POSITION.__START_OF_TEXT;
  185. } else if(_rng.startOffset == _startContainer.textContent.length) {
  186. return $tom.__POSITION.__END_OF_TEXT;
  187. } else {
  188. return $tom.__POSITION.__MIDDLE_OF_TEXT;
  189. }
  190. }
  191. }
  192. return $tom.__POSITION.__END_OF_TEXT;
  193. },
  194. /**
  195. * @private
  196. * selection에 복수의 range가 있을 경우 range를 합친디ㅏ.
  197. * @returns {Object} - native range 객체
  198. * @example
  199. * txSelection.mergeRange(sel);
  200. */
  201. mergeRange: function(sel) {
  202. try {
  203. var _ranges = [];
  204. for(var i=0,_length=sel.rangeCount; i<_length; i++) {
  205. _ranges.push(sel.getRangeAt(i));
  206. }
  207. sel.removeAllRanges();
  208. var _startNode = _ranges[0].startContainer.childNodes[_ranges[0].startOffset];
  209. var _endNode = _ranges[_length - 1].endContainer.childNodes[_ranges[_length - 1].endOffset - 1];
  210. var _rng = this.doc.createRange();
  211. try {
  212. _rng.setStart(_startNode, 0);
  213. } catch (e) {
  214. _rng.collapse(_TRUE);
  215. }
  216. try {
  217. _rng.setEnd(_endNode, _endNode.childNodes.length);
  218. } catch (e) {}
  219. sel.addRange(_rng);
  220. return sel.getRangeAt(0);
  221. } catch(e) {
  222. return sel.getRangeAt(0);
  223. }
  224. },
  225. /**
  226. * @private
  227. * 특정 위치로 range의 시작위치를 지정한다.
  228. * @param {Object} rng - native range 객체
  229. * @param {Element} node - 특정 부모 노드
  230. * @param {Number} offset - 노드의 옵셋
  231. * @example
  232. * txSelection.setStart(range, node, 1);
  233. */
  234. setStart: function(rng, node, offset) {
  235. try {
  236. rng.setStart(node, offset);
  237. } catch (e) {
  238. rng.collapse(_TRUE);
  239. rng.setStart(node, offset);
  240. }
  241. },
  242. /**
  243. * @private
  244. * 특정 위치로 range의 끝위치를 지정한다.
  245. * @param {Object} rng - native range 객체
  246. * @param {Element} node - 특정 부모 노드
  247. * @param {Number} offset - 노드의 옵셋
  248. * @example
  249. * txSelection.setEnd(range, node, 1);
  250. */
  251. setEnd: function(rng, node, offset) {
  252. try {
  253. rng.setEnd(node, offset);
  254. } catch (e) {
  255. rng.collapse(_FALSE);
  256. rng.setEnd(node, offset);
  257. }
  258. },
  259. /**
  260. * 주어진 range를 선택한다.
  261. * @returns {Object} - native selection 객체
  262. * @example
  263. * txSelection.selectRange(range);
  264. */
  265. selectRange: function(rng) {
  266. var _sel = this.getSel();
  267. _sel.removeAllRanges();
  268. _sel.addRange(rng);
  269. }
  270. };
  271. Trex.I.Selection.Trident = /** @lends Trex.Canvas.Selection.prototype */{
  272. /**
  273. * native selection object를 리턴한다.
  274. * @returns {Object} - native selection object
  275. * @example
  276. * txSelection.getSel();
  277. */
  278. getSel: function(){
  279. return this.doc.selection;
  280. },
  281. /**
  282. * 선택된 영역의 텍스트 데이터를 리턴한다.
  283. * @returns {String} - 선택된 영역의 텍스트 데이터
  284. * @example
  285. * txSelection.getText();
  286. */
  287. getText: function() {
  288. return this.getSel().createRange().text;
  289. },
  290. /**
  291. * 선택된 영역의 노드를 리턴한다.
  292. * @returns {Element} - 선택된 영역의 노드
  293. * @example
  294. * txSelection.getNode();
  295. */
  296. getNode: function() {
  297. var _sel = this.getSel();
  298. var _type = _sel.type.toLowerCase();
  299. if (_type === "control") {
  300. return (_sel.createRange().item(0));
  301. } else {
  302. return (_sel.createRange().parentElement());
  303. }
  304. },
  305. /**
  306. * native range 를 생성한다.
  307. * @returns {Object} - native range 객체
  308. * @example
  309. * txSelection.createRange();
  310. */
  311. createRange: function() {
  312. var _sel = this.getSel();
  313. return _sel.createRange();
  314. },
  315. /**
  316. * native text range 를 생성한다.
  317. * @returns {Object} - native text range 객체
  318. * @example
  319. * txSelection.createTextRange();
  320. */
  321. createTextRange: function() {
  322. return this.doc.body.createTextRange();
  323. },
  324. /**
  325. * native range object를 리턴한다.
  326. * @returns {Object} - native range 객체
  327. * @example
  328. * txSelection.getRange();
  329. */
  330. getRange: function(collapse){
  331. var _sel = this.getSel();
  332. var _type = _sel.type.toLowerCase();
  333. if (_type == "none") {
  334. return _sel.createRange() ? _sel.createRange() : function(){
  335. var _rng = this.doc.body.createTextRange();
  336. _rng.collapse(_TRUE);
  337. _rng.select();
  338. return _rng;
  339. }();
  340. }
  341. if (collapse == _NULL) {
  342. return _sel.createRange();
  343. } else {
  344. if (_type === "text") {
  345. var _rng = _sel.createRange();
  346. _rng.collapse(collapse);
  347. _rng.select();
  348. return _sel.createRange();
  349. } else {
  350. if (_type === "control") {
  351. _sel.empty();
  352. }
  353. return _sel.createRange();
  354. }
  355. }
  356. },
  357. /**
  358. * 선택된 영역의 collapse 여부(선택된 영역이 있는지 여부)를 리턴한다.
  359. * @returns {Boolean} - collapse 여부
  360. * @example
  361. * txSelection.isCollapsed();
  362. */
  363. isCollapsed: function() {
  364. var _sel = this.getSel();
  365. var _type = _sel.type.toLowerCase();
  366. if(_type === "none") {
  367. return _TRUE;
  368. } else if(_type === "control") {
  369. return _TRUE;
  370. } else if(_type === "text") {
  371. var _rng = _sel.createRange();
  372. return _rng.compareEndPoints('StartToEnd', _rng) == 0;
  373. } else {
  374. return _TRUE;
  375. }
  376. },
  377. /**
  378. * 선택된 영역을 collapse 시킨다.
  379. * @param {Boolean} toStart - 위치, 시작 = true
  380. * @example
  381. * txSelection.collapse(true);
  382. */
  383. collapse: function(toStart) {
  384. var _sel = this.getSel();
  385. var _type = _sel.type.toLowerCase();
  386. if(_type === "text") {
  387. var _rng = _sel.createRange();
  388. _rng.collapse(toStart);
  389. _rng.select();
  390. return _sel.createRange();
  391. } else {
  392. if(_type === "control") {
  393. _sel.empty();
  394. }
  395. return _sel.createRange();
  396. }
  397. },
  398. /**
  399. * 선택된 영역의 컨트롤 노드(img,object,hr,table,button)를 리턴한다.
  400. * @returns {Element} - 선택된 영역의 노드
  401. * @example
  402. * txSelection.hasControl();
  403. */
  404. getControl: function() {
  405. var _sel = this.getSel();
  406. var _type = _sel.type.toLowerCase();
  407. if (_type === "control") {
  408. var _node = _sel.createRange().item(0);
  409. if($tom.kindOf(_node, '%control')) {
  410. return _node;
  411. } else {
  412. return _NULL;
  413. }
  414. } else {
  415. return _NULL;
  416. }
  417. },
  418. /**
  419. * 선택된 영역이 컨트롤 노드인지 여부를 리턴한다.
  420. * @returns {Boolean} - 컨트롤 노드인지 여부
  421. * @example
  422. * txSelection.hasControl();
  423. */
  424. hasControl: function() {
  425. var _sel = this.getSel();
  426. var _type = _sel.type.toLowerCase();
  427. if (_type === "control") {
  428. return _TRUE;
  429. } else {
  430. return _FALSE;
  431. }
  432. },
  433. /**
  434. * 컨트롤 노드를 선택한다.
  435. * @param {Element} node - 컨트롤 노트
  436. * @example
  437. * txSelection.selectControl(node);
  438. */
  439. selectControl: function(node) {
  440. var _rng = this.doc.body.createControlRange();
  441. _rng.add(node);
  442. _rng.select();
  443. },
  444. /**
  445. * 선택된 영역이 텍스트 데이터 영역의 어떤 위치인지를 리턴한다.
  446. * @returns {Number} - 텍스트 데이터 영역의 어떤 위치인지 <br/>
  447. * 텍스트의 처음 : $tom.__POSITION.__START_OF_TEXT : -1<br/>
  448. * 텍스트의 중간 : $tom.__POSITION.__MIDDLE_OF_TEXT : 0<br/>
  449. * 텍스트의 마지막 : $tom.__POSITION.__END_OF_TEXT : 1
  450. * @example
  451. * txSelection.compareTextPos();
  452. */
  453. compareTextPos: function() {
  454. var _sel = this.getSel();
  455. var _type = _sel.type.toLowerCase();
  456. if(_type === "none") {
  457. var _rng = _sel.createRange();
  458. var _rng2 = _rng.duplicate();
  459. _rng2.moveToElementText(_rng.parentElement());
  460. if ( _rng2.text.trim().replace(Trex.__WORD_JOINER_REGEXP, "").length == 0 ){
  461. return $tom.__POSITION.__EMPTY_TEXT;
  462. } else if(_rng.compareEndPoints('StartToStart', _rng2) == 0) {
  463. return $tom.__POSITION.__START_OF_TEXT;
  464. } else if(_rng.compareEndPoints('EndToEnd', _rng2) == 0) {
  465. return $tom.__POSITION.__END_OF_TEXT;
  466. } else {
  467. return $tom.__POSITION.__MIDDLE_OF_TEXT;
  468. }
  469. }
  470. return $tom.__POSITION.__END_OF_TEXT;
  471. },
  472. /**
  473. * @private
  474. * @reference http://msdn.microsoft.com/en-us/library/ms536745(VS.85).aspx
  475. StartToEnd - Move the start of the TextRange object to the end of the specified oTextRange parameter.
  476. StartToStart - Move the start of the TextRange object to the start of the specified oTextRange parameter.
  477. EndToStart - Move the end of the TextRange object to the start of the specified oTextRange parameter.
  478. EndToEnd - Move the end of the TextRange object to the end of the specified oTextRange parameter.
  479. */
  480. transTextRange: function(rng, node, offset, toStart) {
  481. var _pntRng = this.createTextRange();
  482. var _pntNode = this.win.span(Trex.__WORD_JOINER);
  483. $tom.insertAt(_pntNode, node);
  484. _pntRng.moveToElementText(_pntNode);
  485. $tom.remove(_pntNode);
  486. _pntRng.collapse(_TRUE);
  487. _pntRng.moveStart('character', offset);
  488. if (toStart) {
  489. rng.setEndPoint('StartToStart', _pntRng);
  490. } else {
  491. rng.setEndPoint('EndToEnd', _pntRng);
  492. }
  493. return rng;
  494. },
  495. /**
  496. * @private
  497. * 특정 위치로 range의 시작위치를 지정한다.
  498. * @param {Object} rng - native range 객체
  499. * @param {Element} node - 특정 부모 노드
  500. * @param {Number} offset - 노드의 옵셋
  501. * @example
  502. * txSelection.setStart(range, node, 1);
  503. */
  504. setStart: function(rng, node, offset) {
  505. try {
  506. this.transTextRange(rng, node, offset, _TRUE);
  507. } catch (e) {
  508. console.log(e)
  509. }
  510. return rng;
  511. },
  512. /**
  513. * @private
  514. * 특정 위치로 range의 끝위치를 지정한다.
  515. * @param {Object} rng - native range 객체
  516. * @param {Element} node - 특정 부모 노드
  517. * @param {Number} offset - 노드의 옵셋
  518. * @example
  519. * txSelection.setEnd(range, node, 1);
  520. */
  521. setEnd: function(rng, node, offset) {
  522. try {
  523. this.transTextRange(rng, node, offset, _FALSE);
  524. } catch (e) {
  525. console.log(e)
  526. }
  527. return rng;
  528. },
  529. /**
  530. * 주어진 range를 선택한다.
  531. * @returns {Object} - native selection 객체
  532. * @example
  533. * txSelection.selectRange(range);
  534. */
  535. selectRange: function(rng) {
  536. rng.select();
  537. }
  538. };
  539. Trex.I.Selection.TridentStandard = {
  540. /**
  541. * 선택된 영역의 컨트롤 노드(img,object,hr,table,button)를 리턴한다.
  542. * @returns {Element} - 선택된 영역의 노드
  543. * @example
  544. * txSelection.getControl();
  545. */
  546. getControl: function() {
  547. var _sel = this.getSel();
  548. if(_sel.isCollapsed) {
  549. return null;
  550. }
  551. if ($tom.isElement(_sel.anchorNode)) {
  552. var _node = _sel.anchorNode.childNodes[_sel.anchorOffset];
  553. if ($tom.kindOf(_node, '%control')) {
  554. return _node;
  555. } else {
  556. return null;
  557. }
  558. }
  559. //button
  560. var _prevNode = $tom.previous(_sel.focusNode);
  561. var _nextNode = $tom.next(_sel.anchorNode);
  562. if(_prevNode == _nextNode) {
  563. return $tom.first(_prevNode, '%control');
  564. } else {
  565. return null;
  566. }
  567. },
  568. /**
  569. * 컨트롤 노드를 선택한다.
  570. * @param {Element} node - 컨트롤 노트
  571. * @example
  572. * txSelection.selectControl(node);
  573. */
  574. selectControl: function(node) {
  575. var _rng = this.createRange();
  576. _rng.selectNode(node);
  577. var _sel = this.getSel();
  578. _sel.removeAllRanges();
  579. _sel.addRange(_rng);
  580. }
  581. };
  582. Trex.I.Selection.Gecko = {
  583. };
  584. Trex.I.Selection.Webkit = {
  585. /**
  586. * 선택된 영역의 컨트롤 노드(img,object,hr,table,button)를 리턴한다.
  587. * @returns {Element} - 선택된 영역의 노드
  588. * @example
  589. * txSelection.getControl();
  590. */
  591. getControl: function() {
  592. var _sel = this.getSel();
  593. if(_sel.isCollapsed) {
  594. return _NULL;
  595. }
  596. if ($tom.isElement(_sel.anchorNode)) {
  597. var _node = _sel.anchorNode.childNodes[_sel.anchorOffset];
  598. if ($tom.kindOf(_node, '%control')) {
  599. return _node;
  600. } else {
  601. return _NULL;
  602. }
  603. }
  604. //button
  605. var _prevNode = $tom.previous(_sel.focusNode);
  606. var _nextNode = $tom.next(_sel.anchorNode);
  607. if(_prevNode == _nextNode) {
  608. return $tom.first(_prevNode, '%control');
  609. } else {
  610. return _NULL;
  611. }
  612. },
  613. /**
  614. * 컨트롤 노드를 선택한다.
  615. * @param {Element} node - 컨트롤 노트
  616. * @example
  617. * txSelection.selectControl(node);
  618. */
  619. selectControl: function(node) {
  620. var _rng = this.createRange();
  621. _rng.selectNode(node);
  622. var _sel = this.getSel();
  623. _sel.removeAllRanges();
  624. _sel.addRange(_rng);
  625. }
  626. };
  627. Trex.I.Selection.Presto = {
  628. };
  629. /**
  630. * native selection, range 객체를 wrapping 한 객체로 <br/>
  631. * browser에 따라 필요한 함수들을 mixin한다. <br/>
  632. * 주로 Processor와 연관된 객체에서 호출하며, <br/>
  633. * processor.getTxSel()를 통해서 txSelection를 얻어서 사용한다. <br/>
  634. * native selection 과 구분짓기 위해서 txSelection로 명명한다.
  635. *
  636. * @class
  637. * @param {Object} processor - Processor 객체
  638. */
  639. Trex.Canvas.Selection = Trex.Class.create(/** @lends Trex.Canvas.Selection.prototype */{
  640. /** @ignore */
  641. $mixins: [
  642. Trex.I.Selection.Standard,
  643. (($tx.msie_nonstd)? Trex.I.Selection.Trident: {}),
  644. (($tx.msie_std)? Trex.I.Selection.TridentStandard: {}),
  645. (($tx.gecko)? Trex.I.Selection.Gecko: {}),
  646. (($tx.webkit)? Trex.I.Selection.Webkit: {}),
  647. (($tx.presto)? Trex.I.Selection.Presto: {})
  648. ],
  649. initialize: function(processor) {
  650. this.processor = processor;
  651. this.win = processor.win;
  652. this.doc = processor.doc;
  653. }
  654. });