]> git.za3k.com Git - flowy.git/commitdiff
Allow backspace at the beginning of a todo
authorZachary Vance <vanceza@gmail.com>
Thu, 14 May 2015 03:37:29 +0000 (20:37 -0700)
committerZachary Vance <vanceza@gmail.com>
Thu, 14 May 2015 03:37:29 +0000 (20:37 -0700)
dist/flowy.js
dist/flowy.unwrapped.js
dist/main.html [deleted file]
src/library/cursorToEnd.js
src/views/todo.js

index 4881eb970ed2a38fe6b36e67e4b1e5c53ebdfe6d..bf81f865da48d7718fbb82f03cd6647be3114289 100644 (file)
@@ -20,6 +20,31 @@ function setEndOfContenteditable(contentEditableElement)
     }
 }
 
+function getCaretPosition(editableDiv) {
+  var caretPos = 0,
+    sel, range;
+  if (window.getSelection) {
+    sel = window.getSelection();
+    if (sel.rangeCount) {
+      range = sel.getRangeAt(0);
+      if (range.commonAncestorContainer.parentNode == editableDiv) {
+        caretPos = range.endOffset;
+      }
+    }
+  } else if (document.selection && document.selection.createRange) {
+    range = document.selection.createRange();
+    if (range.parentElement() == editableDiv) {
+      var tempEl = document.createElement("span");
+      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
+      var tempRange = range.duplicate();
+      tempRange.moveToElementText(tempEl);
+      tempRange.setEndPoint("EndToEnd", range);
+      caretPos = tempRange.text.length;
+    }
+  }
+  return caretPos;
+}
+
 /**
  * @depend ../library/cursorToEnd.js
  */
@@ -57,25 +82,35 @@ var TodoView = Backbone.View.extend({
     this.$el.find("> .text").blur();
     return this;
   },
+  isFocusAtBeginning: function() {
+    return getCaretPosition(this.$el.find("> .text")[0]) === 0;
+  },
   decodeText: function(encodedText) {
     return $("<div/>").html(encodedText).text();
   },
   backspace: function(e) {
-    // TODO: Handle backspace at beginning of non-empty line
     if (e.keyCode !== 8 /* backspace */ && e.keyCode !== 46 /* delete */) {
         return;
     }
+    if (this.model.hasChildren()) {
+        return;
+    }
+    var previousNode = this.model.previousNode(this.model.collection);
+    if (!previousNode) {
+        return;
+    }
     if (this.model.get("text") === "") { // Or focus is at the beginning
-        if (this.model.hasChildren()) {
-            return;
-        }
-        var previousNode = this.model.previousNode(this.model.collection);
-        if (!previousNode) {
-            return;
-        }
         e.preventDefault();
         this.model.remove(this.model.collection);
         previousNode.getView().startEditingText({"atEnd":true});
+    } else if (this.isFocusAtBeginning()) {
+        e.preventDefault();
+        var text = this.model.get("text");
+        this.model.remove(this.model.collection);
+        // TODO: Keep focus between the two halves
+        // var focusReminderElement = this.$("<span class=\"focus\"></span>")
+        previousNode.setText(previousNode.get("text")/* + focusReminderElement*/ + text);
+        previousNode.getView().startEditingText(/*{"atMarker": focusReminderElement}*/);
     }
   },
   textChange: function(e) {
index 98ddff2ce80d343b58f555a162b9d5c29245f908..ff2a6ac01223abeb3c7a774a1936cdac0a99d41d 100644 (file)
@@ -19,6 +19,31 @@ function setEndOfContenteditable(contentEditableElement)
     }
 }
 
+function getCaretPosition(editableDiv) {
+  var caretPos = 0,
+    sel, range;
+  if (window.getSelection) {
+    sel = window.getSelection();
+    if (sel.rangeCount) {
+      range = sel.getRangeAt(0);
+      if (range.commonAncestorContainer.parentNode == editableDiv) {
+        caretPos = range.endOffset;
+      }
+    }
+  } else if (document.selection && document.selection.createRange) {
+    range = document.selection.createRange();
+    if (range.parentElement() == editableDiv) {
+      var tempEl = document.createElement("span");
+      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
+      var tempRange = range.duplicate();
+      tempRange.moveToElementText(tempEl);
+      tempRange.setEndPoint("EndToEnd", range);
+      caretPos = tempRange.text.length;
+    }
+  }
+  return caretPos;
+}
+
 /**
  * @depend ../library/cursorToEnd.js
  */
@@ -56,25 +81,35 @@ var TodoView = Backbone.View.extend({
     this.$el.find("> .text").blur();
     return this;
   },
+  isFocusAtBeginning: function() {
+    return getCaretPosition(this.$el.find("> .text")[0]) === 0;
+  },
   decodeText: function(encodedText) {
     return $("<div/>").html(encodedText).text();
   },
   backspace: function(e) {
-    // TODO: Handle backspace at beginning of non-empty line
     if (e.keyCode !== 8 /* backspace */ && e.keyCode !== 46 /* delete */) {
         return;
     }
+    if (this.model.hasChildren()) {
+        return;
+    }
+    var previousNode = this.model.previousNode(this.model.collection);
+    if (!previousNode) {
+        return;
+    }
     if (this.model.get("text") === "") { // Or focus is at the beginning
-        if (this.model.hasChildren()) {
-            return;
-        }
-        var previousNode = this.model.previousNode(this.model.collection);
-        if (!previousNode) {
-            return;
-        }
         e.preventDefault();
         this.model.remove(this.model.collection);
         previousNode.getView().startEditingText({"atEnd":true});
+    } else if (this.isFocusAtBeginning()) {
+        e.preventDefault();
+        var text = this.model.get("text");
+        this.model.remove(this.model.collection);
+        // TODO: Keep focus between the two halves
+        // var focusReminderElement = this.$("<span class=\"focus\"></span>")
+        previousNode.setText(previousNode.get("text")/* + focusReminderElement*/ + text);
+        previousNode.getView().startEditingText(/*{"atMarker": focusReminderElement}*/);
     }
   },
   textChange: function(e) {
diff --git a/dist/main.html b/dist/main.html
deleted file mode 100644 (file)
index ea60868..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
-<head>
-<script src="_bower.js"></script>
-<script src="flowy.js"></script>
-<link rel="stylesheet" type="text/css" href="flowy.css">
-</head>
-<body>
-<div id="todo-app">
-    A todo list:
-    <div id="todo-list">
-
-    </div>
-</div>
-</body>
-</html>
index 555dc60c70906b897dbb95ff12c3971de5591829..cddf800f16a3ae29d594a971e151d7943f3d3fa5 100644 (file)
@@ -18,3 +18,28 @@ function setEndOfContenteditable(contentEditableElement)
         range.select();//Select the range (make it the visible selection
     }
 }
+
+function getCaretPosition(editableDiv) {
+  var caretPos = 0,
+    sel, range;
+  if (window.getSelection) {
+    sel = window.getSelection();
+    if (sel.rangeCount) {
+      range = sel.getRangeAt(0);
+      if (range.commonAncestorContainer.parentNode == editableDiv) {
+        caretPos = range.endOffset;
+      }
+    }
+  } else if (document.selection && document.selection.createRange) {
+    range = document.selection.createRange();
+    if (range.parentElement() == editableDiv) {
+      var tempEl = document.createElement("span");
+      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
+      var tempRange = range.duplicate();
+      tempRange.moveToElementText(tempEl);
+      tempRange.setEndPoint("EndToEnd", range);
+      caretPos = tempRange.text.length;
+    }
+  }
+  return caretPos;
+}
index 119d7f6514f9d8b421f6fd9fbdf9f1cf45ee3ec4..e2ff583060636fe7ee2937f22515497498b5a6ee 100644 (file)
@@ -35,25 +35,35 @@ var TodoView = Backbone.View.extend({
     this.$el.find("> .text").blur();
     return this;
   },
+  isFocusAtBeginning: function() {
+    return getCaretPosition(this.$el.find("> .text")[0]) === 0;
+  },
   decodeText: function(encodedText) {
     return $("<div/>").html(encodedText).text();
   },
   backspace: function(e) {
-    // TODO: Handle backspace at beginning of non-empty line
     if (e.keyCode !== 8 /* backspace */ && e.keyCode !== 46 /* delete */) {
         return;
     }
+    if (this.model.hasChildren()) {
+        return;
+    }
+    var previousNode = this.model.previousNode(this.model.collection);
+    if (!previousNode) {
+        return;
+    }
     if (this.model.get("text") === "") { // Or focus is at the beginning
-        if (this.model.hasChildren()) {
-            return;
-        }
-        var previousNode = this.model.previousNode(this.model.collection);
-        if (!previousNode) {
-            return;
-        }
         e.preventDefault();
         this.model.remove(this.model.collection);
         previousNode.getView().startEditingText({"atEnd":true});
+    } else if (this.isFocusAtBeginning()) {
+        e.preventDefault();
+        var text = this.model.get("text");
+        this.model.remove(this.model.collection);
+        // TODO: Keep focus between the two halves
+        // var focusReminderElement = this.$("<span class=\"focus\"></span>")
+        previousNode.setText(previousNode.get("text")/* + focusReminderElement*/ + text);
+        previousNode.getView().startEditingText(/*{"atMarker": focusReminderElement}*/);
     }
   },
   textChange: function(e) {