splitting blocks from spans
[fnpeditor.git] / src / editor / modules / documentCanvas / canvas / keyboard.js
index eafd091..bd66c6e 100644 (file)
@@ -306,7 +306,7 @@ handlers.push({keys: [KEYS.BACKSPACE, KEYS.DELETE],
             caretTo = 'start';
         }
 
-        if(cursor.isSelecting() && !cursor.isSelectingWithinElement()) {
+        if(cursor.isSelecting()) {
             event.preventDefault();
             var start = cursor.getSelectionStart(),
                 end = cursor.getSelectionEnd();
@@ -359,32 +359,12 @@ handlers.push({keys: [KEYS.BACKSPACE, KEYS.DELETE],
                 event.preventDefault();
                 node.setText('');
             }
-            else if(element.isEmpty()) {
-                event.preventDefault();
-                var parent = element.parent(),
-                    grandParent = parent ? parent.parent() : null;
-                if(!grandParent && parent.children().length === 1) {
-                    return;
-                }
-                if(parent.children().length === 1 && parent.children()[0].sameNode(element)) {
-                    if(grandParent && grandParent.children().length === 1) {
-                        goto = grandParent.wlxmlNode.append({text: ''});
-                    } else {
-                        goto = canvas.getNearestTextElement(direction, element);
-                    }
-                    parent.wlxmlNode.detach();
-                } else {
-                    goto = canvas.getNearestTextElement(direction, element);
-                    element.wlxmlNode.detach();
-                }
-                canvas.setCurrentElement(goto, {caretTo: caretTo});
-            }
             else if(cursorAtOperationEdge) {
                 if(direction === 'below') {
                     element = canvas.getNearestTextElement(direction, element);
                 }
-                if(element) {
-                    goto = element.wlxmlNode.mergeContentUp();
+                if(element && element.wlxmlNode.getIndex() === 0) {
+                    goto = element.wlxmlNode.parent().moveUp();
                     if(goto) {
                         canvas.setCurrentElement(goto.node, {caretTo: goto.offset});
                     }
@@ -399,8 +379,166 @@ handlers.push({keys: [KEYS.BACKSPACE, KEYS.DELETE],
     }
 });
 
+var handleKeyEvent = function(e, s) {
+    keyEventHandlers.some(function(handler) {
+        if(handler.applies(e, s)) {
+            handler.run(e, s);
+            return true;
+        }
+    });
+};
+// todo: whileRemoveWholetext
+var keyEventHandlers = [
+    {
+        applies: function(e, s) {
+            return s.type === 'caret' && (
+                (s.isAtBeginning() && e.key === KEYS.BACKSPACE) ||
+                (s.isAtEnd() && e.key === KEYS.DELETE)
+            );
+        },
+        run: function(e,s) {
+            var direction, caretTo, cursorAtOperationEdge, goto, element;
+
+            if(e.key === KEYS.BACKSPACE) {
+                direction = 'above';
+                caretTo = 'end';
+                cursorAtOperationEdge = s.isAtBeginning();
+                element = s.element;
+            }
+            else {
+                direction = 'below';
+                caretTo = 'start';
+                cursorAtOperationEdge = s.isAtEnd();
+                element = cursorAtOperationEdge && s.canvas.getNearestTextElement(direction, s.element);
+            }
+
+            if(!cursorAtOperationEdge || !element) {
+                return;
+            }
+
+            e.preventDefault();
+
+            s.canvas.wlxmlDocument.transaction(function() {
+                if(element.wlxmlNode.getIndex() === 0) {
+                    goto = element.wlxmlNode.parent().moveUp();
+                    if(goto) {
+                        s.canvas.setCurrentElement(goto.node, {caretTo: goto.offset});
+                    }
+                }
+            }, {
+                metadata: {
+                    description: gettext('Remove text')
+                }
+            });
+        }
+    },
+
+    {
+        applies: function(e,s) {
+            return s.type === 'caret' && s.element.getText().length === 1 && (e.key === KEYS.BACKSPACE || e.key === KEYS.DELETE);
+        },
+        run: function(e,s) {
+            e.preventDefault();
+            e.element.wlxmlNode.setText('');
+            s.canvas.setCurrentElement(s.element, {caretTo: 0});
+        }
+    },
+
+    {
+        applies: function(e, s) {
+            return s.type === 'textSelection' && (e.key === KEYS.BACKSPACE || e.key === KEYS.DELETE);
+        },
+        run: function(e, s) {
+            var direction = 'above',
+                caretTo = 'end',
+                goto;
+
+            if(e.key === KEYS.DELETE) {
+                direction = 'below';
+                caretTo = 'start';
+            }
+
+            e.preventDefault();
+
+            if(s.startsAtBeginning && s.endsAtEnd && s.startElement.sameNode(s.endElement)) {
+                goto = s.startElement;
+                caretTo = s.startOffset;
+            } else if(direction === 'above') {
+                if(s.startsAtBeginning()) {
+                    goto = s.canvas.getNearestTextElement('above', s.startElement);
+                    caretTo = 'end';
+                } else {
+                    goto = s.startElement;
+                    caretTo = s.startOffset;
+                }
+            } else {
+                if(s.endsAtEnd()) {
+                    goto = s.canvas.getNearestTextElement('below', s.startElement);
+                    caretTo = 'start';
+                } else {
+                    goto = s.endElement;
+                    caretTo = 0;
+                }
+            }
+
+            var doc = s.canvas.wlxmlDocument;
+            doc.transaction(function() {
+                
+                doc.deleteText({
+                    from: {
+                        node: s.startElement.wlxmlNode,
+                        offset: s.startOffset
+                    },
+                    to: {
+                        node: s.endElement.wlxmlNode,
+                        offset: s.endOffset
+                    }
+                });
+
+            }, {
+                success: function() {
+                    if(goto) {
+                        s.canvas.setCurrentElement(goto, {caretTo: caretTo});
+                    }
+                }
+            });
+
+        }
+    },
+    {
+        applies: function(e, s) {
+            return s.type === 'caret' && e.key === KEYS.ENTER && !s.element.parent().isRootElement();
+        },
+        run: function(e, s) {
+            var result, goto, gotoOptions;
+            void(e);
+            e.preventDefault();
+            s.canvas.wlxmlDocument.transaction(function() {
+                result = s.element.wlxmlNode.breakContent({offset: s.offset});
+            }, {
+                metadata: {
+                    description: gettext('Splitting text'),
+                    fragment: s.toDocumentFragment()
+                }
+            });
+
+            if(result.emptyText) {
+                goto = result.emptyText;
+                gotoOptions = {};
+            } else {
+                goto = result.second;
+                gotoOptions = {caretTo: 'start'};
+            }
+
+            s.canvas.setCurrentElement(utils.getElementForNode(goto), gotoOptions);
+        }
+    }
+];
+
 return {
-    handleKey: handleKey
+    handleKey: handleKey,
+    handleKeyEvent: handleKeyEvent,
+    KEYS: KEYS
 };
 
 });
\ No newline at end of file