From: Zachary Vance Date: Thu, 28 May 2015 00:44:02 +0000 (-0700) Subject: Make indent preserve focus X-Git-Url: https://git.za3k.com/?a=commitdiff_plain;h=2fc7fee9cab9ed66d86c88619fd0c523a55b8941;p=flowy.git Make indent preserve focus --- diff --git a/dist/flowy.js b/dist/flowy.js index 36a7023..da82859 100644 --- a/dist/flowy.js +++ b/dist/flowy.js @@ -223,6 +223,10 @@ var Shortcut = (function(document, _) { }, addObject: function(element, type, options) { var manager = this; + if (!element) { + console.log("addObject called with no element"); + return; + } object = { element:element, type:type, @@ -355,11 +359,12 @@ var Shortcut = (function(document, _) { } ); }, this); this.shortcutObjects = this.shortcutObjects || []; + var el = this.el; if (objectType === "global") { - Shortcut.globalObject = this.el; + Shortcut.globalObject = el; this._shortcutObject = Shortcut.globalObject; } else { - this._shortcutObject = Shortcut.addObject(this.el, objectType, { view: this }); + this._shortcutObject = Shortcut.addObject(el, objectType, { view: this }); } } View.delegateEvents = function(events) { @@ -407,6 +412,8 @@ var TodoView = Backbone.View.extend({ 'Shortcut("combineNext", "Combine an item with the next item", "del") > .text': "combineNext", 'Shortcut("next", "Next", "down") > .text': 'focusNext', 'Shortcut("previous", "Previous", "up") > .text': 'focusPrevious', + 'Shortcut("right", "Right", "right") > .text': 'rightPressed', + 'Shortcut("left", "Left", "left") > .text': 'leftPressed', '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', @@ -480,6 +487,19 @@ var TodoView = Backbone.View.extend({ previousNode.getView().startEditingText(); return false; }, + leftPressed: function() { + if (!this.duringEditing()) return; // Filter out irrelevant nodes. TODO: Just pay attention to .text to begin with so I can remove this, this is tricky because render takes place after shortcut binding currently + if (!this.isFocusAtBeginning()) return; + var previousNode = this.model.previousNode({ childrenAllowed: true }); + if (!previousNode) return false; + this.stopEditingText(); + previousNode.getView().startEditingText({ atEnd: true }); + return false; + }, + rightPressed: function() { + if (!this.isFocusAtEnd()) return; + return this.focusNext(); + }, combinePrevious: function() { if (this.model.hasChildren()) { return; @@ -522,11 +542,23 @@ var TodoView = Backbone.View.extend({ } }, _maintainingFocus: function(f) { - var el = this.$el.find(".text")[0]; - var start = el.selectionStart, end = el.selectionEnd; - var retVal = f(); - el.focus(); - el.setSelectionRange(start, end); + var el = this.$el.find("> .text")[0]; + var sel = window.getSelection(); + var retVal; + if (sel.rangeCount >= 1) { + var range = sel.getRangeAt(0); + var start = range.startOffset, end = range.endOffset; + retVal = f(); + el = this.$el.find("> .text")[0]; + sel.removeAllRanges(); + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.setStart(el.childNodes[0], start); + range.setEnd(el.childNodes[0], end); + sel.addRange(range); + } else { + retVal = f(); + sel.removeAllRanges(); + } return retVal; }, "delete": function() { @@ -636,8 +668,11 @@ var TodoView = Backbone.View.extend({ removeChild: function(position) { return this.$el.find("> .bullets > *").eq(position).detach(); }, + duringEditing: function() { + return this.$el.find("> .text").is(":focus"); + }, render: function() { - if (this.$el.find("> .text").is(":focus")) { + if (this.duringEditing()) { // Don't re-render during editing return this; } @@ -974,7 +1009,7 @@ var AppView = Backbone.View.extend({ e.save(); }); }); - Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous'] }); + Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right'] }); this.views = {}; // A list of views for each element in the collection this.list.fetch(); this.render(); diff --git a/dist/flowy.unwrapped.js b/dist/flowy.unwrapped.js index eec138a..995c2b6 100644 --- a/dist/flowy.unwrapped.js +++ b/dist/flowy.unwrapped.js @@ -222,6 +222,10 @@ var Shortcut = (function(document, _) { }, addObject: function(element, type, options) { var manager = this; + if (!element) { + console.log("addObject called with no element"); + return; + } object = { element:element, type:type, @@ -354,11 +358,12 @@ var Shortcut = (function(document, _) { } ); }, this); this.shortcutObjects = this.shortcutObjects || []; + var el = this.el; if (objectType === "global") { - Shortcut.globalObject = this.el; + Shortcut.globalObject = el; this._shortcutObject = Shortcut.globalObject; } else { - this._shortcutObject = Shortcut.addObject(this.el, objectType, { view: this }); + this._shortcutObject = Shortcut.addObject(el, objectType, { view: this }); } } View.delegateEvents = function(events) { @@ -406,6 +411,8 @@ var TodoView = Backbone.View.extend({ 'Shortcut("combineNext", "Combine an item with the next item", "del") > .text': "combineNext", 'Shortcut("next", "Next", "down") > .text': 'focusNext', 'Shortcut("previous", "Previous", "up") > .text': 'focusPrevious', + 'Shortcut("right", "Right", "right") > .text': 'rightPressed', + 'Shortcut("left", "Left", "left") > .text': 'leftPressed', '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', @@ -479,6 +486,19 @@ var TodoView = Backbone.View.extend({ previousNode.getView().startEditingText(); return false; }, + leftPressed: function() { + if (!this.duringEditing()) return; // Filter out irrelevant nodes. TODO: Just pay attention to .text to begin with so I can remove this, this is tricky because render takes place after shortcut binding currently + if (!this.isFocusAtBeginning()) return; + var previousNode = this.model.previousNode({ childrenAllowed: true }); + if (!previousNode) return false; + this.stopEditingText(); + previousNode.getView().startEditingText({ atEnd: true }); + return false; + }, + rightPressed: function() { + if (!this.isFocusAtEnd()) return; + return this.focusNext(); + }, combinePrevious: function() { if (this.model.hasChildren()) { return; @@ -521,11 +541,23 @@ var TodoView = Backbone.View.extend({ } }, _maintainingFocus: function(f) { - var el = this.$el.find(".text")[0]; - var start = el.selectionStart, end = el.selectionEnd; - var retVal = f(); - el.focus(); - el.setSelectionRange(start, end); + var el = this.$el.find("> .text")[0]; + var sel = window.getSelection(); + var retVal; + if (sel.rangeCount >= 1) { + var range = sel.getRangeAt(0); + var start = range.startOffset, end = range.endOffset; + retVal = f(); + el = this.$el.find("> .text")[0]; + sel.removeAllRanges(); + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.setStart(el.childNodes[0], start); + range.setEnd(el.childNodes[0], end); + sel.addRange(range); + } else { + retVal = f(); + sel.removeAllRanges(); + } return retVal; }, "delete": function() { @@ -635,8 +667,11 @@ var TodoView = Backbone.View.extend({ removeChild: function(position) { return this.$el.find("> .bullets > *").eq(position).detach(); }, + duringEditing: function() { + return this.$el.find("> .text").is(":focus"); + }, render: function() { - if (this.$el.find("> .text").is(":focus")) { + if (this.duringEditing()) { // Don't re-render during editing return this; } @@ -973,7 +1008,7 @@ var AppView = Backbone.View.extend({ e.save(); }); }); - Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous'] }); + Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right'] }); this.views = {}; // A list of views for each element in the collection this.list.fetch(); this.render(); diff --git a/src/library/shortcut.js b/src/library/shortcut.js index 7ab8fba..7235568 100644 --- a/src/library/shortcut.js +++ b/src/library/shortcut.js @@ -161,6 +161,10 @@ var Shortcut = (function(document, _) { }, addObject: function(element, type, options) { var manager = this; + if (!element) { + console.log("addObject called with no element"); + return; + } object = { element:element, type:type, diff --git a/src/library/viewShortcuts.js b/src/library/viewShortcuts.js index d004864..260d350 100644 --- a/src/library/viewShortcuts.js +++ b/src/library/viewShortcuts.js @@ -29,11 +29,12 @@ } ); }, this); this.shortcutObjects = this.shortcutObjects || []; + var el = this.el; if (objectType === "global") { - Shortcut.globalObject = this.el; + Shortcut.globalObject = el; this._shortcutObject = Shortcut.globalObject; } else { - this._shortcutObject = Shortcut.addObject(this.el, objectType, { view: this }); + this._shortcutObject = Shortcut.addObject(el, objectType, { view: this }); } } View.delegateEvents = function(events) { diff --git a/src/views/app.js b/src/views/app.js index d641806..c1a0c35 100644 --- a/src/views/app.js +++ b/src/views/app.js @@ -85,7 +85,7 @@ var AppView = Backbone.View.extend({ e.save(); }); }); - Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous'] }); + Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right'] }); this.views = {}; // A list of views for each element in the collection this.list.fetch(); this.render(); diff --git a/src/views/todo.js b/src/views/todo.js index 2c7307a..9dc97a9 100644 --- a/src/views/todo.js +++ b/src/views/todo.js @@ -15,6 +15,8 @@ var TodoView = Backbone.View.extend({ 'Shortcut("combineNext", "Combine an item with the next item", "del") > .text': "combineNext", 'Shortcut("next", "Next", "down") > .text': 'focusNext', 'Shortcut("previous", "Previous", "up") > .text': 'focusPrevious', + 'Shortcut("right", "Right", "right") > .text': 'rightPressed', + 'Shortcut("left", "Left", "left") > .text': 'leftPressed', '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', @@ -88,6 +90,19 @@ var TodoView = Backbone.View.extend({ previousNode.getView().startEditingText(); return false; }, + leftPressed: function() { + if (!this.duringEditing()) return; // Filter out irrelevant nodes. TODO: Just pay attention to .text to begin with so I can remove this, this is tricky because render takes place after shortcut binding currently + if (!this.isFocusAtBeginning()) return; + var previousNode = this.model.previousNode({ childrenAllowed: true }); + if (!previousNode) return false; + this.stopEditingText(); + previousNode.getView().startEditingText({ atEnd: true }); + return false; + }, + rightPressed: function() { + if (!this.isFocusAtEnd()) return; + return this.focusNext(); + }, combinePrevious: function() { if (this.model.hasChildren()) { return; @@ -130,11 +145,23 @@ var TodoView = Backbone.View.extend({ } }, _maintainingFocus: function(f) { - var el = this.$el.find(".text")[0]; - var start = el.selectionStart, end = el.selectionEnd; - var retVal = f(); - el.focus(); - el.setSelectionRange(start, end); + var el = this.$el.find("> .text")[0]; + var sel = window.getSelection(); + var retVal; + if (sel.rangeCount >= 1) { + var range = sel.getRangeAt(0); + var start = range.startOffset, end = range.endOffset; + retVal = f(); + el = this.$el.find("> .text")[0]; + sel.removeAllRanges(); + range = document.createRange();//Create a range (a range is a like the selection but invisible) + range.setStart(el.childNodes[0], start); + range.setEnd(el.childNodes[0], end); + sel.addRange(range); + } else { + retVal = f(); + sel.removeAllRanges(); + } return retVal; }, "delete": function() { @@ -244,8 +271,11 @@ var TodoView = Backbone.View.extend({ removeChild: function(position) { return this.$el.find("> .bullets > *").eq(position).detach(); }, + duringEditing: function() { + return this.$el.find("> .text").is(":focus"); + }, render: function() { - if (this.$el.find("> .text").is(":focus")) { + if (this.duringEditing()) { // Don't re-render during editing return this; }