1 define(function(require) {
5 var $ = require('libs/jquery');
7 var Selection = function(canvas, params) {
9 $.extend(this, params);
12 var CaretSelection = function(canvas, params) {
13 Selection.call(this, canvas, params);
15 CaretSelection.prototype = Object.create(Selection.prototype);
16 $.extend(CaretSelection.prototype, {
17 toDocumentFragment: function() {
18 var doc = this.canvas.wlxmlDocument;
19 return doc.createFragment(doc.CaretFragment, {node: this.element.wlxmlNode, offset: this.offset});
21 isAtEdge: function() {
22 return this.isAtBeginning() || this.isAtEnd();
24 isAtBeginning: function() {
25 return this.offset === 0;
28 return this.offset === this.element.getText().length;
32 var TextSelection = function(canvas, params) {
35 Selection.call(this, canvas, params);
37 if(this.anchorElement.sameNode(this.focusElement)) {
38 anchorFirst = this.anchorOffset <= this.focusOffset;
40 /*jshint bitwise: false*/
42 anchorFirst = this.anchorElement.dom[0].compareDocumentPosition(this.focusElement.dom[0]) & Node.DOCUMENT_POSITION_FOLLOWING;
46 this.startElement = this.anchorElement;
47 this.startOffset = this.anchorOffset;
48 this.endElement = this.focusElement;
49 this.endOffset = this.focusOffset;
52 this.startElement = this.focusElement;
53 this.startOffset = this.focusOffset;
54 this.endElement = this.anchorElement;
55 this.endOffset = this.anchorOffset;
58 TextSelection.prototype = Object.create(Selection.prototype);
59 $.extend(TextSelection.prototype, {
60 toDocumentFragment: function() {
61 var doc = this.canvas.wlxmlDocument,
62 anchorNode = this.anchorElement ? this.anchorElement.wlxmlNode : null,
63 focusNode = this.focusElement ? this.focusElement.wlxmlNode : null,
66 if(!anchorNode || !focusNode) {
70 if(anchorNode.isSiblingOf(focusNode)) {
71 return doc.createFragment(doc.TextRangeFragment, {
73 offset1: this.anchorOffset,
75 offset2: this.focusOffset,
79 if(anchorNode.hasSameContextRoot(focusNode)) {
80 var siblingParents = doc.getSiblingParents({node1: anchorNode, node2: focusNode});
81 node1 = siblingParents.node1;
82 node2 = siblingParents.node2;
87 return doc.createFragment(doc.RangeFragment, {
93 startsAtBeginning: function() {
94 return this.startOffset === 0;
96 endsAtEnd: function() {
97 return this.endOffset === this.endElement.getText().length;
101 var NodeSelection = function(canvas, params) {
102 Selection.call(this, canvas, params);
104 NodeSelection.prototype = Object.create(Selection.prototype);
105 $.extend(NodeSelection.prototype, {
106 toDocumentFragment: function() {
107 var doc = this.canvas.wlxmlDocument;
108 doc.createFragment(doc.NodeFragment, {node: this.element.wlxmlNode});
113 var isText = function(node) {
115 return node && node.nodeType === Node.TEXT_NODE && $(node.parentNode).is('[document-text-element]');
119 caret: CaretSelection,
120 textSelection: TextSelection,
121 nodeSelection: NodeSelection
125 fromParams: function(canvas, params) {
126 return new types[params.type](canvas, params);
128 fromNativeSelection: function(canvas) {
130 var nativeSelection = window.getSelection(),
132 element, anchorElement, focusElement;
134 if(nativeSelection.focusNode) {
135 if(nativeSelection.isCollapsed && isText(nativeSelection.focusNode)) {
136 element = canvas.getDocumentElement(nativeSelection.focusNode);
140 offset: element.isEmpty() ? 0 : nativeSelection.getRangeAt(0).startOffset
142 } else if(isText(nativeSelection.focusNode) && isText(nativeSelection.anchorNode)) {
143 anchorElement = canvas.getDocumentElement(nativeSelection.anchorNode);
144 focusElement = canvas.getDocumentElement(nativeSelection.focusNode);
146 type: 'textSelection',
147 anchorElement: anchorElement,
148 anchorOffset: anchorElement.isEmpty() ? 0 : nativeSelection.anchorOffset,
149 focusElement: focusElement,
150 focusOffset: focusElement.isEmpty() ? 0 : nativeSelection.focusOffset
153 } else if((element = canvas.getCurrentNodeElement())) {
155 type: 'nodeSelection',
160 return this.fromParams(canvas, params);