]> git.za3k.com Git - flowy.git/commitdiff
Keep focus in correct place when combining lines
authorZachary Vance <vanceza@gmail.com>
Thu, 14 May 2015 04:06:52 +0000 (21:06 -0700)
committerZachary Vance <vanceza@gmail.com>
Thu, 14 May 2015 04:06:52 +0000 (21:06 -0700)
dist/flowy.js
dist/flowy.unwrapped.js
src/library/cursorToEnd.js
src/views/todo.js

index bf81f865da48d7718fbb82f03cd6647be3114289..87a4d5f51fe6457a584f3c3d49174afeba2723f8 100644 (file)
@@ -45,6 +45,21 @@ function getCaretPosition(editableDiv) {
   return caretPos;
 }
 
+function setRangeAtMarker(markerElement, options) {
+  options = options || {};
+  if (window.getSelection && document.createRange) {
+    var range = document.createRange();
+    range.setStartBefore(markerElement);
+    range.setEndBefore(markerElement);
+    var sel = window.getSelection();
+    sel.removeAllRanges();
+    sel.addRange(range);
+  }
+  if (options.remove) {
+    markerElement.parentNode.removeChild(markerElement);
+  }
+}
+
 /**
  * @depend ../library/cursorToEnd.js
  */
@@ -71,10 +86,17 @@ var TodoView = Backbone.View.extend({
   },
   startEditingText: function(options) {
     options = options || {};
-    if (!options.atEnd) {
-        this.$el.find("> .text").focus();
-    } else {
+    if (options.atEnd) {
         setEndOfContenteditable(this.$el.find("> .text")[0]);
+    } else if (options.atMarker) {
+        var marker = this.$el.find("> .text").find(options.atMarker)[0];
+        if (!marker) {
+            console.log("Marker not found");
+            return;
+        }
+        setRangeAtMarker(marker, {"remove": true});
+    } else {
+        this.$el.find("> .text").focus();
     }
     return this;
   },
@@ -99,18 +121,17 @@ var TodoView = Backbone.View.extend({
     if (!previousNode) {
         return;
     }
-    if (this.model.get("text") === "") { // Or focus is at the beginning
+    if (this.model.get("text") === "") {
         e.preventDefault();
         this.model.remove(this.model.collection);
         previousNode.getView().startEditingText({"atEnd":true});
-    } else if (this.isFocusAtBeginning()) {
+    } else if (this.isFocusAtBeginning() && e.keyCode !== 8 /* backspace only */) {
         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}*/);
+        var focusReminderElement = $('<span class="focus"></span>');
+        previousNode.setText(previousNode.get("text") + '<span class="focus"></span>' + text);
+        previousNode.getView().startEditingText({"atMarker": ".focus"});
     }
   },
   textChange: function(e) {
@@ -160,7 +181,7 @@ var TodoView = Backbone.View.extend({
     }
     return this;
   },
-  template: "<div class=\"text\" contenteditable=\"plaintext-only\">{{text}}</div><div class=\"bullets\"></div>",
+  template: "<div class=\"text\" contenteditable=\"plaintext-only\">{{{text}}}</div><div class=\"bullets\"></div>",
   addChild: function(el, position) {
      if(typeof position === 'undefined' || position === -1) {
         console.log("TodoView:addChild called without a position");
index ff2a6ac01223abeb3c7a774a1936cdac0a99d41d..4cf5f156eade39cc7b53a321e21591768a6ae3a8 100644 (file)
@@ -44,6 +44,21 @@ function getCaretPosition(editableDiv) {
   return caretPos;
 }
 
+function setRangeAtMarker(markerElement, options) {
+  options = options || {};
+  if (window.getSelection && document.createRange) {
+    var range = document.createRange();
+    range.setStartBefore(markerElement);
+    range.setEndBefore(markerElement);
+    var sel = window.getSelection();
+    sel.removeAllRanges();
+    sel.addRange(range);
+  }
+  if (options.remove) {
+    markerElement.parentNode.removeChild(markerElement);
+  }
+}
+
 /**
  * @depend ../library/cursorToEnd.js
  */
@@ -70,10 +85,17 @@ var TodoView = Backbone.View.extend({
   },
   startEditingText: function(options) {
     options = options || {};
-    if (!options.atEnd) {
-        this.$el.find("> .text").focus();
-    } else {
+    if (options.atEnd) {
         setEndOfContenteditable(this.$el.find("> .text")[0]);
+    } else if (options.atMarker) {
+        var marker = this.$el.find("> .text").find(options.atMarker)[0];
+        if (!marker) {
+            console.log("Marker not found");
+            return;
+        }
+        setRangeAtMarker(marker, {"remove": true});
+    } else {
+        this.$el.find("> .text").focus();
     }
     return this;
   },
@@ -98,18 +120,17 @@ var TodoView = Backbone.View.extend({
     if (!previousNode) {
         return;
     }
-    if (this.model.get("text") === "") { // Or focus is at the beginning
+    if (this.model.get("text") === "") {
         e.preventDefault();
         this.model.remove(this.model.collection);
         previousNode.getView().startEditingText({"atEnd":true});
-    } else if (this.isFocusAtBeginning()) {
+    } else if (this.isFocusAtBeginning() && e.keyCode !== 8 /* backspace only */) {
         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}*/);
+        var focusReminderElement = $('<span class="focus"></span>');
+        previousNode.setText(previousNode.get("text") + '<span class="focus"></span>' + text);
+        previousNode.getView().startEditingText({"atMarker": ".focus"});
     }
   },
   textChange: function(e) {
@@ -159,7 +180,7 @@ var TodoView = Backbone.View.extend({
     }
     return this;
   },
-  template: "<div class=\"text\" contenteditable=\"plaintext-only\">{{text}}</div><div class=\"bullets\"></div>",
+  template: "<div class=\"text\" contenteditable=\"plaintext-only\">{{{text}}}</div><div class=\"bullets\"></div>",
   addChild: function(el, position) {
      if(typeof position === 'undefined' || position === -1) {
         console.log("TodoView:addChild called without a position");
index cddf800f16a3ae29d594a971e151d7943f3d3fa5..fae79483bf48db66df3f6b64a3522801a1ff4983 100644 (file)
@@ -43,3 +43,18 @@ function getCaretPosition(editableDiv) {
   }
   return caretPos;
 }
+
+function setRangeAtMarker(markerElement, options) {
+  options = options || {};
+  if (window.getSelection && document.createRange) {
+    var range = document.createRange();
+    range.setStartBefore(markerElement);
+    range.setEndBefore(markerElement);
+    var sel = window.getSelection();
+    sel.removeAllRanges();
+    sel.addRange(range);
+  }
+  if (options.remove) {
+    markerElement.parentNode.removeChild(markerElement);
+  }
+}
index e2ff583060636fe7ee2937f22515497498b5a6ee..979d998c6162c999d25c1cb3db401d5547862e72 100644 (file)
@@ -24,10 +24,17 @@ var TodoView = Backbone.View.extend({
   },
   startEditingText: function(options) {
     options = options || {};
-    if (!options.atEnd) {
-        this.$el.find("> .text").focus();
-    } else {
+    if (options.atEnd) {
         setEndOfContenteditable(this.$el.find("> .text")[0]);
+    } else if (options.atMarker) {
+        var marker = this.$el.find("> .text").find(options.atMarker)[0];
+        if (!marker) {
+            console.log("Marker not found");
+            return;
+        }
+        setRangeAtMarker(marker, {"remove": true});
+    } else {
+        this.$el.find("> .text").focus();
     }
     return this;
   },
@@ -52,18 +59,17 @@ var TodoView = Backbone.View.extend({
     if (!previousNode) {
         return;
     }
-    if (this.model.get("text") === "") { // Or focus is at the beginning
+    if (this.model.get("text") === "") {
         e.preventDefault();
         this.model.remove(this.model.collection);
         previousNode.getView().startEditingText({"atEnd":true});
-    } else if (this.isFocusAtBeginning()) {
+    } else if (this.isFocusAtBeginning() && e.keyCode !== 8 /* backspace only */) {
         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}*/);
+        var focusReminderElement = $('<span class="focus"></span>');
+        previousNode.setText(previousNode.get("text") + '<span class="focus"></span>' + text);
+        previousNode.getView().startEditingText({"atMarker": ".focus"});
     }
   },
   textChange: function(e) {
@@ -113,7 +119,7 @@ var TodoView = Backbone.View.extend({
     }
     return this;
   },
-  template: "<div class=\"text\" contenteditable=\"plaintext-only\">{{text}}</div><div class=\"bullets\"></div>",
+  template: "<div class=\"text\" contenteditable=\"plaintext-only\">{{{text}}}</div><div class=\"bullets\"></div>",
   addChild: function(el, position) {
      if(typeof position === 'undefined' || position === -1) {
         console.log("TodoView:addChild called without a position");