position: fixed;
bottom: -2px;
left: 10px;
- width: 200px;
+ width: 230px;
background: #ffffff;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
}
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,
});
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>')({
"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 = [];
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();
previousNode.getView().startEditingText();
return false;
},
- backspace: function() {
+ combinePrevious: function() {
if (this.model.hasChildren()) {
return;
}
return false;
}
},
- "delete": function(e) {
+ combineNext: function(e) {
if (this.model.hasChildren()) {
return;
}
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\\?>/);
// 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
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();
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();
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);
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,
});
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>')({
"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 = [];
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();
previousNode.getView().startEditingText();
return false;
},
- backspace: function() {
+ combinePrevious: function() {
if (this.model.hasChildren()) {
return;
}
return false;
}
},
- "delete": function(e) {
+ combineNext: function(e) {
if (this.model.hasChildren()) {
return;
}
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\\?>/);
// 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
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();
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();
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);
position: fixed;
bottom: -2px;
left: 10px;
- width: 200px;
+ width: 230px;
background: #ffffff;
.with-dropshadow;
.title {
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,
});
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>')({
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();
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();
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);
"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 = [];
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();
previousNode.getView().startEditingText();
return false;
},
- backspace: function() {
+ combinePrevious: function() {
if (this.model.hasChildren()) {
return;
}
return false;
}
},
- "delete": function(e) {
+ combineNext: function(e) {
if (this.model.hasChildren()) {
return;
}
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\\?>/);
// 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