editor: prevent list action from operating across context root boundries
[fnpeditor.git] / src / editor / modules / documentCanvas / canvas / selection.js
index 790f56d..0d8c4ce 100644 (file)
@@ -17,18 +17,51 @@ $.extend(CaretSelection.prototype, {
     toDocumentFragment: function() {
         var doc = this.canvas.wlxmlDocument;
         return doc.createFragment(doc.CaretFragment, {node: this.element.wlxmlNode, offset: this.offset});
+    },
+    isAtEdge: function() {
+        return this.isAtBeginning() || this.isAtEnd();
+    },
+    isAtBeginning: function() {
+        return this.offset === 0;
+    },
+    isAtEnd: function() {
+        return this.offset === this.element.getText().length;
     }
 });
 
 var TextSelection = function(canvas, params) {
+    var anchorFirst;
+
     Selection.call(this, canvas, params);
+
+    if(this.anchorElement.sameNode(this.focusElement)) {
+        anchorFirst = this.anchorOffset <= this.focusOffset;
+    } else {
+        /*jshint bitwise: false*/
+        /* globals Node */
+        anchorFirst = this.anchorElement.dom[0].compareDocumentPosition(this.focusElement.dom[0]) & Node.DOCUMENT_POSITION_FOLLOWING;
+    }
+
+    if(anchorFirst) {
+        this.startElement = this.anchorElement;
+        this.startOffset = this.anchorOffset;
+        this.endElement = this.focusElement;
+        this.endOffset = this.focusOffset;
+
+    } else {
+        this.startElement = this.focusElement;
+        this.startOffset = this.focusOffset;
+        this.endElement = this.anchorElement;
+        this.endOffset = this.anchorOffset;
+    }
 };
 TextSelection.prototype = Object.create(Selection.prototype);
 $.extend(TextSelection.prototype, {
     toDocumentFragment: function() {
         var doc = this.canvas.wlxmlDocument,
             anchorNode = this.anchorElement ? this.anchorElement.wlxmlNode : null,
-            focusNode = this.focusElement ? this.focusElement.wlxmlNode : null;
+            focusNode = this.focusElement ? this.focusElement.wlxmlNode : null,
+            node1, node2;
         
         if(!anchorNode || !focusNode) {
             return;
@@ -43,12 +76,25 @@ $.extend(TextSelection.prototype, {
             });
         }
         else {
-            var siblingParents = doc.getSiblingParents({node1: anchorNode, node2: focusNode});
+            if(anchorNode.hasSameContextRoot(focusNode)) {
+                var siblingParents = doc.getSiblingParents({node1: anchorNode, node2: focusNode});
+                node1 = siblingParents.node1;
+                node2 = siblingParents.node2;
+            } else {
+                node1 = focusNode;
+                node2 = anchorNode;
+            }
             return doc.createFragment(doc.RangeFragment, {
-                node1: siblingParents.node1,
-                node2: siblingParents.node2
+                node1: node1,
+                node2: node2
             });
         }
+    },
+    startsAtBeginning: function() {
+        return this.startOffset === 0;
+    },
+    endsAtEnd: function() {
+        return this.endOffset === this.endElement.getText().length;
     }
 });
 
@@ -83,21 +129,25 @@ return {
         /* globals window */
         var nativeSelection =  window.getSelection(),
             params = {},
-            element;
+            element, anchorElement, focusElement;
+            
         if(nativeSelection.focusNode) {
             if(nativeSelection.isCollapsed && isText(nativeSelection.focusNode)) {
+                element = canvas.getDocumentElement(nativeSelection.focusNode);
                 params = {
                     type: 'caret',
-                    element: canvas.getDocumentElement(nativeSelection.focusNode),
-                    offset: nativeSelection.focusOffset
+                    element: element,
+                    offset: element.isEmpty() ? 0 : nativeSelection.getRangeAt(0).startOffset
                 };
             } else if(isText(nativeSelection.focusNode) && isText(nativeSelection.anchorNode)) {
+                anchorElement = canvas.getDocumentElement(nativeSelection.anchorNode);
+                focusElement = canvas.getDocumentElement(nativeSelection.focusNode);
                 params = {
                     type: 'textSelection',
-                    anchorElement: canvas.getDocumentElement(nativeSelection.anchorNode),
-                    anchorOffset: nativeSelection.anchorOffset,
-                    focusElement: canvas.getDocumentElement(nativeSelection.focusNode),
-                    focusOffset: nativeSelection.focusOffset
+                    anchorElement: anchorElement,
+                    anchorOffset: anchorElement.isEmpty() ? 0 : nativeSelection.anchorOffset,
+                    focusElement: focusElement,
+                    focusOffset: focusElement.isEmpty() ? 0 : nativeSelection.focusOffset
                 };
             }
         } else if((element = canvas.getCurrentNodeElement())) {