From: Zachary Vance Date: Thu, 14 May 2015 02:55:34 +0000 (-0700) Subject: Make deleting blank nodes focus the end, rather than the beginning of the previous... X-Git-Url: https://git.za3k.com/?a=commitdiff_plain;h=7a8149c8327349639236fcddc061091abf5f91a4;p=flowy.git Make deleting blank nodes focus the end, rather than the beginning of the previous node. Focus end of a (non-nested) contenteditable div is complicated --- diff --git a/dist/flowy.js b/dist/flowy.js index d4213e8..4881eb9 100644 --- a/dist/flowy.js +++ b/dist/flowy.js @@ -1,4 +1,30 @@ $(function(){ +function setEndOfContenteditable(contentEditableElement) +{ + var range,selection; + if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ + { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } + else if(document.selection)//IE 8 and lower + { + range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) + range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + range.select();//Select the range (make it the visible selection + } +} + +/** + * @depend ../library/cursorToEnd.js + */ + + var TodoView = Backbone.View.extend({ tagName: 'div', className: 'todo', @@ -23,8 +49,7 @@ var TodoView = Backbone.View.extend({ if (!options.atEnd) { this.$el.find("> .text").focus(); } else { - this.$el.find("> .text").focus(); - this.$el.find("> .text").val(this.$el.find("> .text")); + setEndOfContenteditable(this.$el.find("> .text")[0]); } return this; }, @@ -44,7 +69,6 @@ var TodoView = Backbone.View.extend({ if (this.model.hasChildren()) { return; } - // TODO: Focus end of previous node var previousNode = this.model.previousNode(this.model.collection); if (!previousNode) { return; @@ -74,6 +98,7 @@ var TodoView = Backbone.View.extend({ // - If there are children, make the new node the first child. Focus the second node. // 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[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])); diff --git a/dist/flowy.unwrapped.js b/dist/flowy.unwrapped.js index aafe463..98ddff2 100644 --- a/dist/flowy.unwrapped.js +++ b/dist/flowy.unwrapped.js @@ -1,3 +1,29 @@ +function setEndOfContenteditable(contentEditableElement) +{ + var range,selection; + if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ + { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } + else if(document.selection)//IE 8 and lower + { + range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) + range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + range.select();//Select the range (make it the visible selection + } +} + +/** + * @depend ../library/cursorToEnd.js + */ + + var TodoView = Backbone.View.extend({ tagName: 'div', className: 'todo', @@ -22,8 +48,7 @@ var TodoView = Backbone.View.extend({ if (!options.atEnd) { this.$el.find("> .text").focus(); } else { - this.$el.find("> .text").focus(); - this.$el.find("> .text").val(this.$el.find("> .text")); + setEndOfContenteditable(this.$el.find("> .text")[0]); } return this; }, @@ -43,7 +68,6 @@ var TodoView = Backbone.View.extend({ if (this.model.hasChildren()) { return; } - // TODO: Focus end of previous node var previousNode = this.model.previousNode(this.model.collection); if (!previousNode) { return; @@ -73,6 +97,7 @@ var TodoView = Backbone.View.extend({ // - If there are children, make the new node the first child. Focus the second node. // 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[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])); diff --git a/src/library/cursorToEnd.js b/src/library/cursorToEnd.js new file mode 100644 index 0000000..555dc60 --- /dev/null +++ b/src/library/cursorToEnd.js @@ -0,0 +1,20 @@ +function setEndOfContenteditable(contentEditableElement) +{ + var range,selection; + if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ + { + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + selection = window.getSelection();//get the selection object (allows you to change selection) + selection.removeAllRanges();//remove any selections already made + selection.addRange(range);//make the range you have just created the visible selection + } + else if(document.selection)//IE 8 and lower + { + range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) + range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range + range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start + range.select();//Select the range (make it the visible selection + } +} diff --git a/src/views/todo.js b/src/views/todo.js index dd66f4c..119d7f6 100644 --- a/src/views/todo.js +++ b/src/views/todo.js @@ -1,3 +1,8 @@ +/** + * @depend ../library/cursorToEnd.js + */ + + var TodoView = Backbone.View.extend({ tagName: 'div', className: 'todo', @@ -22,8 +27,7 @@ var TodoView = Backbone.View.extend({ if (!options.atEnd) { this.$el.find("> .text").focus(); } else { - this.$el.find("> .text").focus(); - this.$el.find("> .text").val(this.$el.find("> .text")); + setEndOfContenteditable(this.$el.find("> .text")[0]); } return this; }, @@ -43,7 +47,6 @@ var TodoView = Backbone.View.extend({ if (this.model.hasChildren()) { return; } - // TODO: Focus end of previous node var previousNode = this.model.previousNode(this.model.collection); if (!previousNode) { return; @@ -73,6 +76,7 @@ var TodoView = Backbone.View.extend({ // - If there are children, make the new node the first child. Focus the second node. // 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[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]));