},
_displayKeybinding: function(shortcut, options) {
options = _.defaults({}, options, { displayMultiple: true, allowRebind: false });
- var keybindings = shortcut.keybinding.split(",");
+ var keybindings = shortcut.keybinding;
+ if (typeof(keybindings) === 'string') keybindings = [keybindings];
if (!options.displayMultiple && keybindings.length > 1) {
keybindings = [keybindings[0]];
}
var undelegateEvents = View.undelegateEvents;
var ShortcutRegex = /^Shortcut\("([^")]*)", ?"([^")]*)", ?"([^")]*)"\) (.*)$/;
function delegate(id, description, defaultKeybinding, objectType, callback){
+ if (typeof(defaultKeybinding) !== 'string' && defaultKeybinding.split) defaultKeybinding = defaultKeybinding.split(',');
var shortcut = Shortcut.registerShortcut({
id: id,
description: description,
'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("indent", "Not Done - Indent", "tab,alt+shift+right") > .text': 'indent',
+ 'Shortcut("indent", "Not Done - Indent", "tab") > .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',
return false;
},
indent: function() {
- // Last child of previous sibling, then nothing
- console.log("Indent not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.indent(this.model.collection);
+ return false;
},
outdent: function() {
- // After parent, then nothing
- console.log("Outdent not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.outdent(this.model.collection);
},
expand: function() {
console.log("Expand not implemented"); // TODO
console.log("Zoom not implemented"); // TODO
},
moveDown: function() {
- // After next sibling, then as first child of next node after parent, then up one level, then nothing
- console.log("Move not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.moveDown(this.model.collection);
},
moveUp: function() {
- // Before previous sibling, then as last child of previous node of parent, then before parent, then nothing
- console.log("Move not implemented"); // TODO
- this.moveTo({keyboard:true});
- },
- moveTo: function(loc, options) {
- loc = _.defaults({}, loc, { parent: this.model.getParent(this.model.collection), index: this.model.getParent(this.model.collection).findChild(this.model.id) });
- options = _.defaults({}, options, {
- keyboard: false, // Whether the action was done with keyboard vs mouse (affects UI focus)
- });
- console.log("Move not implemented");
- return false;
+ // TODO: maintain focus
+ this.model.moveUp(this.model.collection);
},
textChange: function(e) {
var collection = this.model.collection;
this.set("bullets", bullets);
return this;
},
+ moveTo: function(newLocation, collection) {
+ if (collection.rootId == this.id) {
+ console.log("Cannot move root");
+ return this;
+ }
+ var existingLocation = {
+ parent: this.getParent(collection),
+ index: this.getParent(collection).findChild(this.id),
+ };
+ newLocation = _.defaults({}, newLocation, existingLocation);
+ var newChildren;
+ if (newLocation.parent === existingLocation.parent && newLocation.index === existingLocation.index) {
+ // No-op
+ } else if (newLocation.parent === this.parent) {
+ // We moved to a new location under the same parent.
+ newChildren = _.clone(newLocation.parent.get("bullets"));
+ newChildren.splice(existingLocation.index, 1);
+ newLocation.index = (newLocation.index < existingLocation.index) ? newLocation.index : newLocation.index - 1; // Adjust indices for insertion
+ newChildren.splice(existingLocation.index, 0, this.id);
+
+ newLocation.parent.save("bullets", newChildren);
+ this.save();
+ } else {
+ // We moved to a new parent
+ newChildren = _.clone(existingLocation.parent.get("bullets"));
+ newChildren.splice(existingLocation.index, 1);
+ existingLocation.parent.save("bullets", newChildren);
+
+ newLocation.parent.insertChild(this, newLocation.index);
+ newLocation.parent.save();
+ this.save();
+ }
+ collection.trigger("move", this, existingLocation);
+ return this;
+ },
+ moveUp: function(collection) {
+ // Before previous sibling, then as last child of previous node of parent, then before parent, then nothing
+ },
+ moveDown: function(collection) {
+ // After next sibling, then as first child of next node after parent, then up one level, then nothing
+ },
+ indent: function(collection) {
+ // Last child of previous sibling, then nothing
+ var previous = this.getPreviousSibling(collection);
+ if (!previous) return undefined;
+ return this.moveTo({
+ parent: previous,
+ index: previous.getChildrenCount(),
+ }, collection);
+ },
+ outdent: function(collection) {
+ // After parent, then nothing
+ },
removeChild: function(childTodoModel, collection) {
if (childTodoModel.get("bullets").length > 0) {
console.log("Cannot delete node with children.");
this.list = options.list || new FlowyDocModel();
this.list.app = this;
this.listenTo(this.list, 'add', this.addOne);
+ this.listenTo(this.list, 'move', this.moveOne);
this.listenTo(this.list, 'reset', this.addAll);
var self = this;
this.$("#reset-button").on("click", function() {
addOne: function(todo) {
this.renderTodo(todo);
},
+ moveOne: function(todo, oldLocation) {
+ var view = this.getView(todo);
+
+ var oldParent = oldLocation.parent;
+ var oldParentView;
+ if (oldParent) oldParentView = this.getView(oldParent);
+ if (oldParentView) {
+ // Remove from old parent
+ }
+
+ this.renderTodo(todo, { rerender: true }); // Don't remove existing view since it's still valid.
+ },
toggleShortcuts: function() {
this.$(".shortcuts").toggle();
},
search: function() {
console.log("Search not yet implemented"); // TODO
},
- renderTodo: function(todo) {
- if (this.getView(todo)) {
+ renderTodo: function(todo, options) {
+ options = _.defaults({}, options, {
+ rerender: false,
+ });
+ if (this.getView(todo) && !options.rerender) {
console.log("View rendered more than once for todo #" + todo.id);
return;
}
getView: function(model) {
return this.views[model.id];
},
+ removeView: function(model) {
+ delete this.views[model.id];
+ },
addAll: function() {
this.views = {};
this.$("#todo-list").html(null);
},
_displayKeybinding: function(shortcut, options) {
options = _.defaults({}, options, { displayMultiple: true, allowRebind: false });
- var keybindings = shortcut.keybinding.split(",");
+ var keybindings = shortcut.keybinding;
+ if (typeof(keybindings) === 'string') keybindings = [keybindings];
if (!options.displayMultiple && keybindings.length > 1) {
keybindings = [keybindings[0]];
}
var undelegateEvents = View.undelegateEvents;
var ShortcutRegex = /^Shortcut\("([^")]*)", ?"([^")]*)", ?"([^")]*)"\) (.*)$/;
function delegate(id, description, defaultKeybinding, objectType, callback){
+ if (typeof(defaultKeybinding) !== 'string' && defaultKeybinding.split) defaultKeybinding = defaultKeybinding.split(',');
var shortcut = Shortcut.registerShortcut({
id: id,
description: description,
'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("indent", "Not Done - Indent", "tab,alt+shift+right") > .text': 'indent',
+ 'Shortcut("indent", "Not Done - Indent", "tab") > .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',
return false;
},
indent: function() {
- // Last child of previous sibling, then nothing
- console.log("Indent not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.indent(this.model.collection);
+ return false;
},
outdent: function() {
- // After parent, then nothing
- console.log("Outdent not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.outdent(this.model.collection);
},
expand: function() {
console.log("Expand not implemented"); // TODO
console.log("Zoom not implemented"); // TODO
},
moveDown: function() {
- // After next sibling, then as first child of next node after parent, then up one level, then nothing
- console.log("Move not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.moveDown(this.model.collection);
},
moveUp: function() {
- // Before previous sibling, then as last child of previous node of parent, then before parent, then nothing
- console.log("Move not implemented"); // TODO
- this.moveTo({keyboard:true});
- },
- moveTo: function(loc, options) {
- loc = _.defaults({}, loc, { parent: this.model.getParent(this.model.collection), index: this.model.getParent(this.model.collection).findChild(this.model.id) });
- options = _.defaults({}, options, {
- keyboard: false, // Whether the action was done with keyboard vs mouse (affects UI focus)
- });
- console.log("Move not implemented");
- return false;
+ // TODO: maintain focus
+ this.model.moveUp(this.model.collection);
},
textChange: function(e) {
var collection = this.model.collection;
this.set("bullets", bullets);
return this;
},
+ moveTo: function(newLocation, collection) {
+ if (collection.rootId == this.id) {
+ console.log("Cannot move root");
+ return this;
+ }
+ var existingLocation = {
+ parent: this.getParent(collection),
+ index: this.getParent(collection).findChild(this.id),
+ };
+ newLocation = _.defaults({}, newLocation, existingLocation);
+ var newChildren;
+ if (newLocation.parent === existingLocation.parent && newLocation.index === existingLocation.index) {
+ // No-op
+ } else if (newLocation.parent === this.parent) {
+ // We moved to a new location under the same parent.
+ newChildren = _.clone(newLocation.parent.get("bullets"));
+ newChildren.splice(existingLocation.index, 1);
+ newLocation.index = (newLocation.index < existingLocation.index) ? newLocation.index : newLocation.index - 1; // Adjust indices for insertion
+ newChildren.splice(existingLocation.index, 0, this.id);
+
+ newLocation.parent.save("bullets", newChildren);
+ this.save();
+ } else {
+ // We moved to a new parent
+ newChildren = _.clone(existingLocation.parent.get("bullets"));
+ newChildren.splice(existingLocation.index, 1);
+ existingLocation.parent.save("bullets", newChildren);
+
+ newLocation.parent.insertChild(this, newLocation.index);
+ newLocation.parent.save();
+ this.save();
+ }
+ collection.trigger("move", this, existingLocation);
+ return this;
+ },
+ moveUp: function(collection) {
+ // Before previous sibling, then as last child of previous node of parent, then before parent, then nothing
+ },
+ moveDown: function(collection) {
+ // After next sibling, then as first child of next node after parent, then up one level, then nothing
+ },
+ indent: function(collection) {
+ // Last child of previous sibling, then nothing
+ var previous = this.getPreviousSibling(collection);
+ if (!previous) return undefined;
+ return this.moveTo({
+ parent: previous,
+ index: previous.getChildrenCount(),
+ }, collection);
+ },
+ outdent: function(collection) {
+ // After parent, then nothing
+ },
removeChild: function(childTodoModel, collection) {
if (childTodoModel.get("bullets").length > 0) {
console.log("Cannot delete node with children.");
this.list = options.list || new FlowyDocModel();
this.list.app = this;
this.listenTo(this.list, 'add', this.addOne);
+ this.listenTo(this.list, 'move', this.moveOne);
this.listenTo(this.list, 'reset', this.addAll);
var self = this;
this.$("#reset-button").on("click", function() {
addOne: function(todo) {
this.renderTodo(todo);
},
+ moveOne: function(todo, oldLocation) {
+ var view = this.getView(todo);
+
+ var oldParent = oldLocation.parent;
+ var oldParentView;
+ if (oldParent) oldParentView = this.getView(oldParent);
+ if (oldParentView) {
+ // Remove from old parent
+ }
+
+ this.renderTodo(todo, { rerender: true }); // Don't remove existing view since it's still valid.
+ },
toggleShortcuts: function() {
this.$(".shortcuts").toggle();
},
search: function() {
console.log("Search not yet implemented"); // TODO
},
- renderTodo: function(todo) {
- if (this.getView(todo)) {
+ renderTodo: function(todo, options) {
+ options = _.defaults({}, options, {
+ rerender: false,
+ });
+ if (this.getView(todo) && !options.rerender) {
console.log("View rendered more than once for todo #" + todo.id);
return;
}
getView: function(model) {
return this.views[model.id];
},
+ removeView: function(model) {
+ delete this.views[model.id];
+ },
addAll: function() {
this.views = {};
this.$("#todo-list").html(null);
},
_displayKeybinding: function(shortcut, options) {
options = _.defaults({}, options, { displayMultiple: true, allowRebind: false });
- var keybindings = shortcut.keybinding.split(",");
+ var keybindings = shortcut.keybinding;
+ if (typeof(keybindings) === 'string') keybindings = [keybindings];
if (!options.displayMultiple && keybindings.length > 1) {
keybindings = [keybindings[0]];
}
var undelegateEvents = View.undelegateEvents;
var ShortcutRegex = /^Shortcut\("([^")]*)", ?"([^")]*)", ?"([^")]*)"\) (.*)$/;
function delegate(id, description, defaultKeybinding, objectType, callback){
+ if (typeof(defaultKeybinding) !== 'string' && defaultKeybinding.split) defaultKeybinding = defaultKeybinding.split(',');
var shortcut = Shortcut.registerShortcut({
id: id,
description: description,
this.set("bullets", bullets);
return this;
},
+ moveTo: function(newLocation, collection) {
+ if (collection.rootId == this.id) {
+ console.log("Cannot move root");
+ return this;
+ }
+ var existingLocation = {
+ parent: this.getParent(collection),
+ index: this.getParent(collection).findChild(this.id),
+ };
+ newLocation = _.defaults({}, newLocation, existingLocation);
+ var newChildren;
+ if (newLocation.parent === existingLocation.parent && newLocation.index === existingLocation.index) {
+ // No-op
+ } else if (newLocation.parent === this.parent) {
+ // We moved to a new location under the same parent.
+ newChildren = _.clone(newLocation.parent.get("bullets"));
+ newChildren.splice(existingLocation.index, 1);
+ newLocation.index = (newLocation.index < existingLocation.index) ? newLocation.index : newLocation.index - 1; // Adjust indices for insertion
+ newChildren.splice(existingLocation.index, 0, this.id);
+
+ newLocation.parent.save("bullets", newChildren);
+ this.save();
+ } else {
+ // We moved to a new parent
+ newChildren = _.clone(existingLocation.parent.get("bullets"));
+ newChildren.splice(existingLocation.index, 1);
+ existingLocation.parent.save("bullets", newChildren);
+
+ newLocation.parent.insertChild(this, newLocation.index);
+ newLocation.parent.save();
+ this.save();
+ }
+ collection.trigger("move", this, existingLocation);
+ return this;
+ },
+ moveUp: function(collection) {
+ // Before previous sibling, then as last child of previous node of parent, then before parent, then nothing
+ },
+ moveDown: function(collection) {
+ // After next sibling, then as first child of next node after parent, then up one level, then nothing
+ },
+ indent: function(collection) {
+ // Last child of previous sibling, then nothing
+ var previous = this.getPreviousSibling(collection);
+ if (!previous) return undefined;
+ return this.moveTo({
+ parent: previous,
+ index: previous.getChildrenCount(),
+ }, collection);
+ },
+ outdent: function(collection) {
+ // After parent, then nothing
+ },
removeChild: function(childTodoModel, collection) {
if (childTodoModel.get("bullets").length > 0) {
console.log("Cannot delete node with children.");
this.list = options.list || new FlowyDocModel();
this.list.app = this;
this.listenTo(this.list, 'add', this.addOne);
+ this.listenTo(this.list, 'move', this.moveOne);
this.listenTo(this.list, 'reset', this.addAll);
var self = this;
this.$("#reset-button").on("click", function() {
addOne: function(todo) {
this.renderTodo(todo);
},
+ moveOne: function(todo, oldLocation) {
+ var view = this.getView(todo);
+
+ var oldParent = oldLocation.parent;
+ var oldParentView;
+ if (oldParent) oldParentView = this.getView(oldParent);
+ if (oldParentView) {
+ // Remove from old parent
+ }
+
+ this.renderTodo(todo, { rerender: true }); // Don't remove existing view since it's still valid.
+ },
toggleShortcuts: function() {
this.$(".shortcuts").toggle();
},
search: function() {
console.log("Search not yet implemented"); // TODO
},
- renderTodo: function(todo) {
- if (this.getView(todo)) {
+ renderTodo: function(todo, options) {
+ options = _.defaults({}, options, {
+ rerender: false,
+ });
+ if (this.getView(todo) && !options.rerender) {
console.log("View rendered more than once for todo #" + todo.id);
return;
}
getView: function(model) {
return this.views[model.id];
},
+ removeView: function(model) {
+ delete this.views[model.id];
+ },
addAll: function() {
this.views = {};
this.$("#todo-list").html(null);
'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("indent", "Not Done - Indent", "tab,alt+shift+right") > .text': 'indent',
+ 'Shortcut("indent", "Not Done - Indent", "tab") > .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',
return false;
},
indent: function() {
- // Last child of previous sibling, then nothing
- console.log("Indent not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.indent(this.model.collection);
+ return false;
},
outdent: function() {
- // After parent, then nothing
- console.log("Outdent not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.outdent(this.model.collection);
},
expand: function() {
console.log("Expand not implemented"); // TODO
console.log("Zoom not implemented"); // TODO
},
moveDown: function() {
- // After next sibling, then as first child of next node after parent, then up one level, then nothing
- console.log("Move not implemented"); // TODO
- this.moveTo({keyboard:true});
+ // TODO: maintain focus
+ this.model.moveDown(this.model.collection);
},
moveUp: function() {
- // Before previous sibling, then as last child of previous node of parent, then before parent, then nothing
- console.log("Move not implemented"); // TODO
- this.moveTo({keyboard:true});
- },
- moveTo: function(loc, options) {
- loc = _.defaults({}, loc, { parent: this.model.getParent(this.model.collection), index: this.model.getParent(this.model.collection).findChild(this.model.id) });
- options = _.defaults({}, options, {
- keyboard: false, // Whether the action was done with keyboard vs mouse (affects UI focus)
- });
- console.log("Move not implemented");
- return false;
+ // TODO: maintain focus
+ this.model.moveUp(this.model.collection);
},
textChange: function(e) {
var collection = this.model.collection;