]> git.za3k.com Git - flowy.git/commitdiff
Add fake versions of all shortcuts, make 'delete' key at end of line work
authorZachary Vance <vanceza@gmail.com>
Sat, 23 May 2015 02:05:45 +0000 (19:05 -0700)
committerZachary Vance <vanceza@gmail.com>
Sat, 23 May 2015 02:05:49 +0000 (19:05 -0700)
dist/flowy.css
dist/flowy.js
dist/flowy.unwrapped.js
src/css/flowy.less
src/library/shortcut.js
src/views/app.js
src/views/todo.js

index 1ae3cd256c9a265c646dd2a4b274bc742fe3cb58..7cdb9fdce5ba9e7bdbf96d6329c2682adcdedbe4 100644 (file)
@@ -39,7 +39,7 @@ body {
   position: fixed;
   bottom: -2px;
   left: 10px;
-  width: 200px;
+  width: 230px;
   background: #ffffff;
   box-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
 }
index 0542e72bd6f8633750075f3a325ca6bac416c83c..ddb473c78eca7d1517b829ffd14991903804a47b 100644 (file)
@@ -281,7 +281,7 @@ var Shortcut = (function(document, _) {
                 displayMultiple: true, // Display multiple shortcuts or just the canonical one?
                 allowRebind: false, // Insert javascript to allow rebinding shortcuts
                 highlightRepeats: true, // Warn about shortcuts which are bound to multiple actions (if user can remap shortcuts) // TODO
-                shortcuts: _.sortBy(this.shortcuts, 'description'),
+                shortcuts: this.shortcuts,//_.sortBy(this.shortcuts, 'description'),
                 noDisplay: [], // ids not to display
                 includeElement: true,
             });
@@ -308,7 +308,7 @@ var Shortcut = (function(document, _) {
 
             var keybindingHTML = _.map(keybindings, function(keybinding) {
                 return _.template("<code><%= keybinding %></code>")({keybinding: _.escape(keybinding)});
-            }).join("<br/>");
+            }).join(",<br/>");
             if (options.allowRebind) {
                 // Ugh, way too magic, how do I use an actual function here
                 return _.template('<div onclick="Shortcut.userRebindShortcut(Shortcut.shortcuts[\'<%= id %>\'], {element: this })"><%= keybindingHTML %></div>')({
@@ -401,11 +401,19 @@ var TodoView = Backbone.View.extend({
     "input > .text": "textChange",
     "blur > .text": "render", // Because the model shouldn't update the view during active editing, add a re-render at the end
     "keydown > .text": "keydown",
-    'Shortcut("toggleComplete", "Complete", "ctrl+enter") > .text': "toggleComplete",
-    'Shortcut("backspace", "Combine an item with the previous item", "backspace") > .text': "backspace",
-    'Shortcut("delete", "Combine an item with the next item", "del") > .text': "delete",
+    'Shortcut("combinePrevious", "Combine an item with the previous item", "backspace") > .text': "combinePrevious",
+    'Shortcut("combineNext", "Combine an item with the next item", "del") > .text': "combineNext",
     'Shortcut("next", "Next", "down") > .text': 'next',
     'Shortcut("previous", "Previous", "up") > .text': 'previous',
+    'Shortcut("zoomIn", "Not Done - Zoom in", "alt+right") > .text': 'zoomIn',
+    'Shortcut("zoomOut", "Not Done - Zoom out", "alt+left") > .text': 'zoomOut',
+    'Shortcut("expand", "Not Done - Expand / collapse", "ctrl+space") > .text': 'expand',
+    'Shortcut("indent", "Not Done - Indent", "tab,alt+shift+right") > .text': 'indent',
+    'Shortcut("outdent", "Not Done - Outdent", "shift+tab,alt+shift+left") > .text': 'outdent',
+    'Shortcut("moveDown", "Not Done - Move", "alt+shift+down") > .text': 'moveDown',
+    'Shortcut("moveUp", "Not Done - Move", "alt+shift+up") > .text': 'moveUp',
+    'Shortcut("toggleComplete", "Complete", "ctrl+enter") > .text': "toggleComplete",
+    'Shortcut("delete", "Not Done - Delete", "ctrl+shift+del") > .text': 'delete',
   },
   initialize: function() {
     this.childViewPositions = [];
@@ -436,7 +444,7 @@ var TodoView = Backbone.View.extend({
     return getCaretPosition(this.$el.find("> .text")[0]) === 0;
   },
   isFocusAtEnd: function() {
-    return false; // TODO
+    return getCaretPosition(this.$el.find("> .text")[0]) === this.$el.find("> .text").text().length;
   },
   decodeText: function(encodedText) {
     return $("<div/>").html(encodedText).text();
@@ -469,7 +477,7 @@ var TodoView = Backbone.View.extend({
     previousNode.getView().startEditingText();
     return false;
   },
-  backspace: function() {
+  combinePrevious: function() {
     if (this.model.hasChildren()) {
         return;
     }
@@ -489,7 +497,7 @@ var TodoView = Backbone.View.extend({
         return false;
     }
   },
-  "delete": function(e) {
+  combineNext: function(e) {
     if (this.model.hasChildren()) {
         return;
     }
@@ -510,6 +518,30 @@ var TodoView = Backbone.View.extend({
         return false;
     }   
   },
+  "delete": function() {
+    console.log("Delete not implemented"); // TODO
+  },
+  indent: function() {
+    console.log("Indent not implemented"); // TODO
+  },
+  outdent: function() {
+    console.log("Outdent not implemented"); // TODO
+  },
+  expand: function() {
+    console.log("Expand not implemented"); // TODO
+  },
+  zoomIn: function() {
+    console.log("Zoom not implemented"); // TODO
+  },
+  zoomOut: function() {
+    console.log("Zoom not implemented"); // TODO
+  },
+  moveDown: function() {
+    console.log("Move not implemented"); // TODO
+  },
+  moveUp: function() {
+    console.log("Move not implemented"); // TODO
+  },
   textChange: function(e) {
     var collection = this.model.collection;
     var lines = $(e.target).html().split(/<br\\?>/);
@@ -531,7 +563,10 @@ var TodoView = Backbone.View.extend({
     // NOTE: Copy-paste is overridden so there can't be more than one line break.
     // NOTE: Shift-enter is overridden and handled seperately, to allow "notes" spanning multiple lines.
     // NOTE: Line break on empty bullet should shift it up the tree for perfect imitation; this is stupid so I ignored it.
-
+     } else if ((lines.length === 2 && lines[0] === "" && lines[1] === "") || (lines.length === 3 && lines[0] === "" && lines[1] === "" && lines[2] === "")) { // Enter pressed on empty line
+        this.model.setText(this.decodeText(lines[0]));
+        this.stopEditingText();
+        this.outdent();
      } else if ((lines.length === 2 && lines[1].length === 0) || (lines.length === 3 && lines[1].length === 0 && lines[2].length === 0)) { // Line break at end
         this.model.setText(this.decodeText(lines[0]));
         var emptyAfter = this.model.addTodoAfter({text: this.decodeText(lines[1])}, collection); // Child or not depending on whether this has children
@@ -815,6 +850,11 @@ var appDefaults = { list: todos };
 var AppView = Backbone.View.extend({
     el: $("#todo-app"),
     shortcutObject: "global",
+    events: {
+        'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+?") > .text': 'toggleShortcuts',
+        'Shortcut("toggleShowCompleted", "Not Done - Show/hide completed", "ctrl+o") > .text': 'toggleShowCompleted',
+        'Shortcut("search", "Not Done - Search", "esc") > .text': 'search',
+    },
     initialize: function(options) {
         options = _.defaults({}, options, appDefaults);
         this.list = options.list || new FlowyDocModel();
@@ -832,7 +872,7 @@ var AppView = Backbone.View.extend({
                 e.save();
             });
         });
-        Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['backspace', 'delete', 'next', 'previous'] });
+        Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous'] });
         this.views = {}; // A list of views for each element in the collection
         this.list.fetch();
         this.render();
@@ -843,6 +883,15 @@ var AppView = Backbone.View.extend({
     addOne: function(todo) {
         this.renderTodo(todo);
     },
+    toggleShortcuts: function() {
+        this.$(".shortcuts").toggle();
+    },
+    toggleShowCompleted: function() {
+        console.log("Toggling show/hide not yet implemented"); // TODO
+    },
+    search: function() {
+        console.log("Search not yet implemented"); // TODO
+    },
     renderTodo: function(todo) {
         if (this.getView(todo)) {
             console.log("View rendered more than once for todo #" + todo.id);
index 7aa17612d20bfe525a5eb5101f0b344e8882e336..7f61de89982e0389d8f4228e5ac6c334a1fcba9c 100644 (file)
@@ -280,7 +280,7 @@ var Shortcut = (function(document, _) {
                 displayMultiple: true, // Display multiple shortcuts or just the canonical one?
                 allowRebind: false, // Insert javascript to allow rebinding shortcuts
                 highlightRepeats: true, // Warn about shortcuts which are bound to multiple actions (if user can remap shortcuts) // TODO
-                shortcuts: _.sortBy(this.shortcuts, 'description'),
+                shortcuts: this.shortcuts,//_.sortBy(this.shortcuts, 'description'),
                 noDisplay: [], // ids not to display
                 includeElement: true,
             });
@@ -307,7 +307,7 @@ var Shortcut = (function(document, _) {
 
             var keybindingHTML = _.map(keybindings, function(keybinding) {
                 return _.template("<code><%= keybinding %></code>")({keybinding: _.escape(keybinding)});
-            }).join("<br/>");
+            }).join(",<br/>");
             if (options.allowRebind) {
                 // Ugh, way too magic, how do I use an actual function here
                 return _.template('<div onclick="Shortcut.userRebindShortcut(Shortcut.shortcuts[\'<%= id %>\'], {element: this })"><%= keybindingHTML %></div>')({
@@ -400,11 +400,19 @@ var TodoView = Backbone.View.extend({
     "input > .text": "textChange",
     "blur > .text": "render", // Because the model shouldn't update the view during active editing, add a re-render at the end
     "keydown > .text": "keydown",
-    'Shortcut("toggleComplete", "Complete", "ctrl+enter") > .text': "toggleComplete",
-    'Shortcut("backspace", "Combine an item with the previous item", "backspace") > .text': "backspace",
-    'Shortcut("delete", "Combine an item with the next item", "del") > .text': "delete",
+    'Shortcut("combinePrevious", "Combine an item with the previous item", "backspace") > .text': "combinePrevious",
+    'Shortcut("combineNext", "Combine an item with the next item", "del") > .text': "combineNext",
     'Shortcut("next", "Next", "down") > .text': 'next',
     'Shortcut("previous", "Previous", "up") > .text': 'previous',
+    'Shortcut("zoomIn", "Not Done - Zoom in", "alt+right") > .text': 'zoomIn',
+    'Shortcut("zoomOut", "Not Done - Zoom out", "alt+left") > .text': 'zoomOut',
+    'Shortcut("expand", "Not Done - Expand / collapse", "ctrl+space") > .text': 'expand',
+    'Shortcut("indent", "Not Done - Indent", "tab,alt+shift+right") > .text': 'indent',
+    'Shortcut("outdent", "Not Done - Outdent", "shift+tab,alt+shift+left") > .text': 'outdent',
+    'Shortcut("moveDown", "Not Done - Move", "alt+shift+down") > .text': 'moveDown',
+    'Shortcut("moveUp", "Not Done - Move", "alt+shift+up") > .text': 'moveUp',
+    'Shortcut("toggleComplete", "Complete", "ctrl+enter") > .text': "toggleComplete",
+    'Shortcut("delete", "Not Done - Delete", "ctrl+shift+del") > .text': 'delete',
   },
   initialize: function() {
     this.childViewPositions = [];
@@ -435,7 +443,7 @@ var TodoView = Backbone.View.extend({
     return getCaretPosition(this.$el.find("> .text")[0]) === 0;
   },
   isFocusAtEnd: function() {
-    return false; // TODO
+    return getCaretPosition(this.$el.find("> .text")[0]) === this.$el.find("> .text").text().length;
   },
   decodeText: function(encodedText) {
     return $("<div/>").html(encodedText).text();
@@ -468,7 +476,7 @@ var TodoView = Backbone.View.extend({
     previousNode.getView().startEditingText();
     return false;
   },
-  backspace: function() {
+  combinePrevious: function() {
     if (this.model.hasChildren()) {
         return;
     }
@@ -488,7 +496,7 @@ var TodoView = Backbone.View.extend({
         return false;
     }
   },
-  "delete": function(e) {
+  combineNext: function(e) {
     if (this.model.hasChildren()) {
         return;
     }
@@ -509,6 +517,30 @@ var TodoView = Backbone.View.extend({
         return false;
     }   
   },
+  "delete": function() {
+    console.log("Delete not implemented"); // TODO
+  },
+  indent: function() {
+    console.log("Indent not implemented"); // TODO
+  },
+  outdent: function() {
+    console.log("Outdent not implemented"); // TODO
+  },
+  expand: function() {
+    console.log("Expand not implemented"); // TODO
+  },
+  zoomIn: function() {
+    console.log("Zoom not implemented"); // TODO
+  },
+  zoomOut: function() {
+    console.log("Zoom not implemented"); // TODO
+  },
+  moveDown: function() {
+    console.log("Move not implemented"); // TODO
+  },
+  moveUp: function() {
+    console.log("Move not implemented"); // TODO
+  },
   textChange: function(e) {
     var collection = this.model.collection;
     var lines = $(e.target).html().split(/<br\\?>/);
@@ -530,7 +562,10 @@ var TodoView = Backbone.View.extend({
     // NOTE: Copy-paste is overridden so there can't be more than one line break.
     // NOTE: Shift-enter is overridden and handled seperately, to allow "notes" spanning multiple lines.
     // NOTE: Line break on empty bullet should shift it up the tree for perfect imitation; this is stupid so I ignored it.
-
+     } else if ((lines.length === 2 && lines[0] === "" && lines[1] === "") || (lines.length === 3 && lines[0] === "" && lines[1] === "" && lines[2] === "")) { // Enter pressed on empty line
+        this.model.setText(this.decodeText(lines[0]));
+        this.stopEditingText();
+        this.outdent();
      } else if ((lines.length === 2 && lines[1].length === 0) || (lines.length === 3 && lines[1].length === 0 && lines[2].length === 0)) { // Line break at end
         this.model.setText(this.decodeText(lines[0]));
         var emptyAfter = this.model.addTodoAfter({text: this.decodeText(lines[1])}, collection); // Child or not depending on whether this has children
@@ -814,6 +849,11 @@ var appDefaults = { list: todos };
 var AppView = Backbone.View.extend({
     el: $("#todo-app"),
     shortcutObject: "global",
+    events: {
+        'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+?") > .text': 'toggleShortcuts',
+        'Shortcut("toggleShowCompleted", "Not Done - Show/hide completed", "ctrl+o") > .text': 'toggleShowCompleted',
+        'Shortcut("search", "Not Done - Search", "esc") > .text': 'search',
+    },
     initialize: function(options) {
         options = _.defaults({}, options, appDefaults);
         this.list = options.list || new FlowyDocModel();
@@ -831,7 +871,7 @@ var AppView = Backbone.View.extend({
                 e.save();
             });
         });
-        Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['backspace', 'delete', 'next', 'previous'] });
+        Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous'] });
         this.views = {}; // A list of views for each element in the collection
         this.list.fetch();
         this.render();
@@ -842,6 +882,15 @@ var AppView = Backbone.View.extend({
     addOne: function(todo) {
         this.renderTodo(todo);
     },
+    toggleShortcuts: function() {
+        this.$(".shortcuts").toggle();
+    },
+    toggleShowCompleted: function() {
+        console.log("Toggling show/hide not yet implemented"); // TODO
+    },
+    search: function() {
+        console.log("Search not yet implemented"); // TODO
+    },
     renderTodo: function(todo) {
         if (this.getView(todo)) {
             console.log("View rendered more than once for todo #" + todo.id);
index 9092e00d1b2da9ada9226732b9d7ae0d1a45459a..617e7aef5ca0718e843147ec9978a7a2925d8c67 100644 (file)
@@ -48,7 +48,7 @@ body {
     position: fixed;
     bottom: -2px;
     left: 10px;
-    width: 200px;
+    width: 230px;
     background: #ffffff;
     .with-dropshadow;
     .title {
index a5bf9464771d8b448fc17c27f0505ce933e39ff4..8c97dbdf21c4725f4d79323d466fa8117a322ec8 100644 (file)
@@ -219,7 +219,7 @@ var Shortcut = (function(document, _) {
                 displayMultiple: true, // Display multiple shortcuts or just the canonical one?
                 allowRebind: false, // Insert javascript to allow rebinding shortcuts
                 highlightRepeats: true, // Warn about shortcuts which are bound to multiple actions (if user can remap shortcuts) // TODO
-                shortcuts: _.sortBy(this.shortcuts, 'description'),
+                shortcuts: this.shortcuts,//_.sortBy(this.shortcuts, 'description'),
                 noDisplay: [], // ids not to display
                 includeElement: true,
             });
@@ -246,7 +246,7 @@ var Shortcut = (function(document, _) {
 
             var keybindingHTML = _.map(keybindings, function(keybinding) {
                 return _.template("<code><%= keybinding %></code>")({keybinding: _.escape(keybinding)});
-            }).join("<br/>");
+            }).join(",<br/>");
             if (options.allowRebind) {
                 // Ugh, way too magic, how do I use an actual function here
                 return _.template('<div onclick="Shortcut.userRebindShortcut(Shortcut.shortcuts[\'<%= id %>\'], {element: this })"><%= keybindingHTML %></div>')({
index ee325d853586862a5269e5384de573dbb66c6833..dc920501c103892a66f4b9cc5f82ec918396ba35 100644 (file)
@@ -62,6 +62,11 @@ var appDefaults = { list: todos };
 var AppView = Backbone.View.extend({
     el: $("#todo-app"),
     shortcutObject: "global",
+    events: {
+        'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+?") > .text': 'toggleShortcuts',
+        'Shortcut("toggleShowCompleted", "Not Done - Show/hide completed", "ctrl+o") > .text': 'toggleShowCompleted',
+        'Shortcut("search", "Not Done - Search", "esc") > .text': 'search',
+    },
     initialize: function(options) {
         options = _.defaults({}, options, appDefaults);
         this.list = options.list || new FlowyDocModel();
@@ -79,7 +84,7 @@ var AppView = Backbone.View.extend({
                 e.save();
             });
         });
-        Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['backspace', 'delete', 'next', 'previous'] });
+        Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous'] });
         this.views = {}; // A list of views for each element in the collection
         this.list.fetch();
         this.render();
@@ -90,6 +95,15 @@ var AppView = Backbone.View.extend({
     addOne: function(todo) {
         this.renderTodo(todo);
     },
+    toggleShortcuts: function() {
+        this.$(".shortcuts").toggle();
+    },
+    toggleShowCompleted: function() {
+        console.log("Toggling show/hide not yet implemented"); // TODO
+    },
+    search: function() {
+        console.log("Search not yet implemented"); // TODO
+    },
     renderTodo: function(todo) {
         if (this.getView(todo)) {
             console.log("View rendered more than once for todo #" + todo.id);
index e4be2e5d0b2139b65f936d0ed210ebc5866272c4..91fd153706b5110cf7ffecf10bdaa32e296b54a5 100644 (file)
@@ -11,11 +11,19 @@ var TodoView = Backbone.View.extend({
     "input > .text": "textChange",
     "blur > .text": "render", // Because the model shouldn't update the view during active editing, add a re-render at the end
     "keydown > .text": "keydown",
-    'Shortcut("toggleComplete", "Complete", "ctrl+enter") > .text': "toggleComplete",
-    'Shortcut("backspace", "Combine an item with the previous item", "backspace") > .text': "backspace",
-    'Shortcut("delete", "Combine an item with the next item", "del") > .text': "delete",
+    'Shortcut("combinePrevious", "Combine an item with the previous item", "backspace") > .text': "combinePrevious",
+    'Shortcut("combineNext", "Combine an item with the next item", "del") > .text': "combineNext",
     'Shortcut("next", "Next", "down") > .text': 'next',
     'Shortcut("previous", "Previous", "up") > .text': 'previous',
+    'Shortcut("zoomIn", "Not Done - Zoom in", "alt+right") > .text': 'zoomIn',
+    'Shortcut("zoomOut", "Not Done - Zoom out", "alt+left") > .text': 'zoomOut',
+    'Shortcut("expand", "Not Done - Expand / collapse", "ctrl+space") > .text': 'expand',
+    'Shortcut("indent", "Not Done - Indent", "tab,alt+shift+right") > .text': 'indent',
+    'Shortcut("outdent", "Not Done - Outdent", "shift+tab,alt+shift+left") > .text': 'outdent',
+    'Shortcut("moveDown", "Not Done - Move", "alt+shift+down") > .text': 'moveDown',
+    'Shortcut("moveUp", "Not Done - Move", "alt+shift+up") > .text': 'moveUp',
+    'Shortcut("toggleComplete", "Complete", "ctrl+enter") > .text': "toggleComplete",
+    'Shortcut("delete", "Not Done - Delete", "ctrl+shift+del") > .text': 'delete',
   },
   initialize: function() {
     this.childViewPositions = [];
@@ -46,7 +54,7 @@ var TodoView = Backbone.View.extend({
     return getCaretPosition(this.$el.find("> .text")[0]) === 0;
   },
   isFocusAtEnd: function() {
-    return false; // TODO
+    return getCaretPosition(this.$el.find("> .text")[0]) === this.$el.find("> .text").text().length;
   },
   decodeText: function(encodedText) {
     return $("<div/>").html(encodedText).text();
@@ -79,7 +87,7 @@ var TodoView = Backbone.View.extend({
     previousNode.getView().startEditingText();
     return false;
   },
-  backspace: function() {
+  combinePrevious: function() {
     if (this.model.hasChildren()) {
         return;
     }
@@ -99,7 +107,7 @@ var TodoView = Backbone.View.extend({
         return false;
     }
   },
-  "delete": function(e) {
+  combineNext: function(e) {
     if (this.model.hasChildren()) {
         return;
     }
@@ -120,6 +128,30 @@ var TodoView = Backbone.View.extend({
         return false;
     }   
   },
+  "delete": function() {
+    console.log("Delete not implemented"); // TODO
+  },
+  indent: function() {
+    console.log("Indent not implemented"); // TODO
+  },
+  outdent: function() {
+    console.log("Outdent not implemented"); // TODO
+  },
+  expand: function() {
+    console.log("Expand not implemented"); // TODO
+  },
+  zoomIn: function() {
+    console.log("Zoom not implemented"); // TODO
+  },
+  zoomOut: function() {
+    console.log("Zoom not implemented"); // TODO
+  },
+  moveDown: function() {
+    console.log("Move not implemented"); // TODO
+  },
+  moveUp: function() {
+    console.log("Move not implemented"); // TODO
+  },
   textChange: function(e) {
     var collection = this.model.collection;
     var lines = $(e.target).html().split(/<br\\?>/);
@@ -141,7 +173,10 @@ var TodoView = Backbone.View.extend({
     // NOTE: Copy-paste is overridden so there can't be more than one line break.
     // NOTE: Shift-enter is overridden and handled seperately, to allow "notes" spanning multiple lines.
     // NOTE: Line break on empty bullet should shift it up the tree for perfect imitation; this is stupid so I ignored it.
-
+     } else if ((lines.length === 2 && lines[0] === "" && lines[1] === "") || (lines.length === 3 && lines[0] === "" && lines[1] === "" && lines[2] === "")) { // Enter pressed on empty line
+        this.model.setText(this.decodeText(lines[0]));
+        this.stopEditingText();
+        this.outdent();
      } else if ((lines.length === 2 && lines[1].length === 0) || (lines.length === 3 && lines[1].length === 0 && lines[2].length === 0)) { // Line break at end
         this.model.setText(this.decodeText(lines[0]));
         var emptyAfter = this.model.addTodoAfter({text: this.decodeText(lines[1])}, collection); // Child or not depending on whether this has children