/**
* @fileOverview
* 선택된 영역을 북마크하여
* 포커스된 document가 변경되거나 DOM 조작을 하더라도 선택 영역이 유지되도록 한다.
* Processor 에서 주로 사용된다.
*/
/**
* 선택된 영역을 북마크하여
* 포커스된 document가 변경되거나 DOM 조작을 하더라도 선택 영역이 유지되도록 하는 객체로
* native range 객체에 있는 5가지 프로퍼티만 저장한다.
* 주로 Processor와 연관된 객체에서 호출하며,
* processor.getBookmark()를 통해서 bookmark를 얻어서 사용한다.
*
* @class
*/
Trex.Canvas.Bookmark = Trex.Class.create(/** @lends Trex.Canvas.Bookmark.prototype */{
startContainer: _NULL,
startOffset: 0,
endContainer: _NULL,
endOffset: 0,
initialize: function(processor) {
this.processor = processor;
this.win = processor.win;
this.doc = processor.doc;
this.dummy = function() {
return processor.newDummy();
};
},
/**
* 시작위치와 끝위치를 동일하게 북마크를 수정한다.
* @param {Boolean} toStart - 위치, 시작 = true
* @example
* bookmark.collapse(true);
*/
collapse: function (toStart) {
if (toStart) {
this.updateEnd(this.startContainer, this.startOffset);
} else {
this.updateStart(this.endContainer, this.endOffset);
}
},
/**
* native range 객체로 북마크를 수정한다.
* @param {Object} rng - native range 객체
* @example
* bookmark.save(range);
*/
save: function(rng) {
this.updateStart(rng.startContainer, rng.startOffset);
this.updateEnd(rng.endContainer, rng.endOffset);
},
/**
* 특정 노드의 앞과 뒤로 북마크를 수정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.saveAroundNode(node);
*/
saveAroundNode: function (node) {
this.updateStartBefore($tom.top(node));
this.updateEndAfter($tom.bottom(node));
},
/**
* 특정 노드의 처음으로 북마크를 수정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.saveIntoFirst(node);
*/
saveIntoFirst: function(node) {
var _node = $tom.top(node);
this.updateEndBefore(_node);
this.collapse(_FALSE);
},
/**
* 특정 노드의 마지막으로 북마크를 수정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.saveIntoLast(node);
*/
saveIntoLast: function(node) {
var _node = $tom.bottom(node);
this.updateEndBefore(_node);
this.collapse(_FALSE);
},
/**
* 특정 노드의 이전으로 북마크를 수정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.saveNextTo(node);
*/
savePreviousTo: function(node) {
if($tom.previous(node)) {
var _node = $tom.top($tom.previous(node));
this.updateEndAfter(_node);
} else {
this.updateEndBefore(node);
}
this.collapse(_FALSE);
},
/**
* 특정 노드의 다음으로 북마크를 수정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.saveNextTo(node);
*/
saveNextTo: function(node) {
if($tom.next(node)) {
var _node = $tom.top($tom.next(node));
this.updateEndBefore(_node);
} else {
this.updateEndAfter(node);
}
this.collapse(_FALSE);
},
/**
* marker node로 북마크를 수정한다.
* @param {Object} marker - marker 객체
* @example
* bookmark.saveWithMarker(marker);
*/
saveWithMarker: function(marker) {
if (marker.checkCollapsed()) { //collapsed
this.updateEndAfter(marker.endMarker);
this.collapse(_FALSE);
} else {
this.updateStartBefore(marker.startMarker);
this.updateEndAfter(marker.endMarker);
}
},
/**
* txSelection가지고 저장된 북마크를 선택한다.
* @param {Object} txSelection - txSelection 객체
* @example
* bookmark.select(txSelection);
*/
select: function(txSel) {
if (this.isValid()) {
var _rng = txSel.createTextRange();
try {
txSel.setStart(_rng, this.startContainer, this.startOffset);
txSel.setEnd(_rng, this.endContainer, this.endOffset);
} catch (e) {
console.log(e)
}
txSel.selectRange(_rng);
}
this.reset();
},
isValid: function() {
return this.isValidStartContainer() && this.isValidEndContainer();
},
isValidStartContainer: function() {
return this.doc.body === $tom.body(this.startContainer);
},
isValidEndContainer: function() {
return this.doc.body === $tom.body(this.endContainer);
},
/**
* @private
* 시작 관련 프로퍼티를 특정 위치로 지정한다.
* @param {Element} node - 특정 부모 노드
* @param {Number} offset - 노드의 옵셋
* @example
* bookmark.updateStart(node, 1);
*/
updateStart: function(node, offset) {
this.startContainer = node;
this.startOffset = offset;
},
/**
* @private
* 시작 관련 프로퍼티를 특정 위치로 이전으로 지정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.updateStartBefore(node);
*/
updateStartBefore: function(node) {
var _tNode = this.dummy();
$tom.insertAt(_tNode, node);
this.startContainer = _tNode;
this.startOffset = 0;
},
/**
* @private
* 시작 관련 프로퍼티를 특정 위치로 다음으로 지정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.updateStartAfter(node);
*/
updateStartAfter: function(node) {
var _tNode = this.dummy();
$tom.insertNext(_tNode, node);
this.startContainer = _tNode;
this.startOffset = 0;
},
/**
* @private
* 끝 관련 프로퍼티를 특정 위치로 지정한다.
* @param {Element} node - 특정 부모 노드
* @param {Number} offset - 노드의 옵셋
* @example
* bookmark.updateEnd(node, 1);
*/
updateEnd: function(node, offset) {
this.endContainer = node;
this.endOffset = offset;
},
/**
* @private
* 끝 관련 프로퍼티를 특정 위치로 이전으로 지정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.updateEndBefore(node);
*/
updateEndBefore: function(node) {
var _tNode = this.dummy();
if (node.nodeName && node.nodeName.toUpperCase() == "P" && !node.nodeValue) { // Note: 마지막 조건( !node.nodeValue)은 무의미한데..
$tom.append(node, _tNode);
}else {
$tom.insertAt(_tNode, node);
}
this.endContainer = _tNode;
this.endOffset = _tNode.length;
},
/**
* @private
* 끝 관련 프로퍼티를 특정 위치로 다음으로 지정한다.
* @param {Element} node - 특정 노드
* @example
* bookmark.updateEndAfter(node);
*/
updateEndAfter: function(node) {
var _tNode = this.dummy();
$tom.insertNext(_tNode, node);
this.endContainer = _tNode;
this.endOffset = _tNode.length;
},
/**
* @private
* 북마크를 초기화한다.
* @returns {Boolean} - collapse 여부
* @example
* bookmark.reset();
*/
reset: function() {
this.startContainer = _NULL;
this.startOffset = 0;
this.endContainer = _NULL;
this.endOffset = 0;
}
});