var el = this.el;
if (objectType === "global") {
Shortcut.globalObject = el;
+ Shortcut.globalObject.options = { view: this };
this._shortcutObject = Shortcut.globalObject;
} else {
this._shortcutObject = Shortcut.addObject(el, objectType, { view: this });
toggleCollapsed: function() {
this.save({collapsed: !this.get("collapsed")});
},
+ _setText: function(text) {
+ return this.save({text: text});
+ },
setText: function(text) {
- this.save({text: text});
+ return Actions.App.act(new Actions.ChangeText(this, text));
},
hasChildren: function() {
return this.get("bullets").length > 0;
this.set("bullets", bullets);
return this;
},
+ getLocation: function() {
+ return {
+ parent: this.getParent(),
+ index: this.getParent().findChild(this.id),
+ };
+ },
moveTo: function(newLocation) {
if (this.isRoot()) {
console.log("Cannot move root");
return this;
}
- var existingLocation = {
- parent: this.getParent(),
- index: this.getParent().findChild(this.id),
- };
+ var existingLocation = this.getLocation();
newLocation = _.defaults({}, newLocation, existingLocation);
+ return Actions.App.act(new Actions.MoveBullet(this, newLocation));
+ },
+ _moveTo: function(newLocation) {
+ var existingLocation = this.getLocation();
var newChildren;
if (newLocation.parent === existingLocation.parent && newLocation.index === existingLocation.index) {
// No-op
Actions = {};
-Actions.AppendWords = function(array, word) {
- this.array = array;
- this.word = word;
+Actions.MoveBullet = function(bullet, newLocation) {
+ this.bullet = bullet;
+ this.oldLocation = bullet.getLocation();
+ this.newLocation = newLocation;
};
-Actions.AppendWords.prototype = _.extend(new BaseAction(), {
+Actions.MoveBullet.prototype = _.extend(new BaseAction(), {
apply: function() {
- this.array.push(this.word);
+ return this.bullet._moveTo(this.newLocation);
},
rewind: function() {
- var a = this.array.pop();
- if (a !== this.word) {
- throw "Rewind faiiiiiled :(";
- }
+ return this.bullet._moveTo(this.oldLocation);
+ },
+});
+
+Actions.ChangeText = function(bullet, newText) {
+ this.bullet = bullet;
+ this.oldText = bullet.get("text");
+ this.newText = newText;
+};
+Actions.ChangeText.prototype = _.extend(new BaseAction(), {
+ apply: function() {
+ return this.bullet._setText(this.newText);
+ },
+ rewind: function() {
+ return this.bullet._setText(this.oldText);
},
});
el: $("#todo-app"),
shortcutObject: "global",
events: {
- 'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+shift+/") > .text': 'toggleShortcuts',
- 'Shortcut("toggleShowCompleted", "Show/hide completed", "ctrl+o") > .text': 'toggleShowCompleted',
- 'Shortcut("search", "Not Done - Search", "esc") > .text': 'search',
+ 'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+shift+/") body': 'toggleShortcuts',
+ 'Shortcut("toggleShowCompleted", "Show/hide completed", "ctrl+o") body': 'toggleShowCompleted',
+ 'Shortcut("search", "Not Done - Search", "esc") body': 'search',
+ 'Shortcut("undo", "Undo", "ctrl+z") body': 'undo',
+ 'Shortcut("redo", "Redo", "ctrl+shift+z,ctrl+y") body': 'redo',
},
initialize: function(options) {
options = _.defaults({}, options, appDefaults);
e.save();
});
});
- Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right'] });
+ Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right', 'undo', 'redo'] });
this.views = {}; // A list of views for each element in the collection
- this.history = [];
- this.history.redo = [];
+ Actions.App = this;
+ this.undoRedoHistory = {undo: [], redo:[]}; // Linear zipper
this.list.fetch();
this.render();
},
}
},
act: function(action) {
- action.apply();
- this.history.push(action);
- this.history.redo = [];
+ var retVal = action.apply();
+ this.undoRedoHistory.undo.push(action);
+ this.undoRedoHistory.redo = [];
+ return retVal;
},
undo: function() {
- var action = this.history.pop();
- if (!action) throw "Rewind called with empty history stack";
- action.rewind();
- this.history.redo.push(action);
+ var action = this.undoRedoHistory.undo.pop();
+ if (!action) {
+ console.log("Rewind called with empty history stack");
+ return;
+ }
+ var retVal = action.rewind();
+ this.undoRedoHistory.redo.push(action);
+ return retVal;
},
redo: function() {
- var action = this.history.redo.pop();
- if (!action) throw "Replay called with empty redo stack";
+ var action = this.undoRedoHistory.redo.pop();
+ if (!action) {
+ console.log("Replay called with empty redo stack");
+ return;
+ }
action.reapply();
- this.history.push(action);
+ this.undoRedoHistory.undo.push(action);
},
toggleShortcuts: function() {
this.$(".shortcuts").toggle();
var el = this.el;
if (objectType === "global") {
Shortcut.globalObject = el;
+ Shortcut.globalObject.options = { view: this };
this._shortcutObject = Shortcut.globalObject;
} else {
this._shortcutObject = Shortcut.addObject(el, objectType, { view: this });
toggleCollapsed: function() {
this.save({collapsed: !this.get("collapsed")});
},
+ _setText: function(text) {
+ return this.save({text: text});
+ },
setText: function(text) {
- this.save({text: text});
+ return Actions.App.act(new Actions.ChangeText(this, text));
},
hasChildren: function() {
return this.get("bullets").length > 0;
this.set("bullets", bullets);
return this;
},
+ getLocation: function() {
+ return {
+ parent: this.getParent(),
+ index: this.getParent().findChild(this.id),
+ };
+ },
moveTo: function(newLocation) {
if (this.isRoot()) {
console.log("Cannot move root");
return this;
}
- var existingLocation = {
- parent: this.getParent(),
- index: this.getParent().findChild(this.id),
- };
+ var existingLocation = this.getLocation();
newLocation = _.defaults({}, newLocation, existingLocation);
+ return Actions.App.act(new Actions.MoveBullet(this, newLocation));
+ },
+ _moveTo: function(newLocation) {
+ var existingLocation = this.getLocation();
var newChildren;
if (newLocation.parent === existingLocation.parent && newLocation.index === existingLocation.index) {
// No-op
Actions = {};
-Actions.AppendWords = function(array, word) {
- this.array = array;
- this.word = word;
+Actions.MoveBullet = function(bullet, newLocation) {
+ this.bullet = bullet;
+ this.oldLocation = bullet.getLocation();
+ this.newLocation = newLocation;
};
-Actions.AppendWords.prototype = _.extend(new BaseAction(), {
+Actions.MoveBullet.prototype = _.extend(new BaseAction(), {
apply: function() {
- this.array.push(this.word);
+ return this.bullet._moveTo(this.newLocation);
},
rewind: function() {
- var a = this.array.pop();
- if (a !== this.word) {
- throw "Rewind faiiiiiled :(";
- }
+ return this.bullet._moveTo(this.oldLocation);
+ },
+});
+
+Actions.ChangeText = function(bullet, newText) {
+ this.bullet = bullet;
+ this.oldText = bullet.get("text");
+ this.newText = newText;
+};
+Actions.ChangeText.prototype = _.extend(new BaseAction(), {
+ apply: function() {
+ return this.bullet._setText(this.newText);
+ },
+ rewind: function() {
+ return this.bullet._setText(this.oldText);
},
});
el: $("#todo-app"),
shortcutObject: "global",
events: {
- 'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+shift+/") > .text': 'toggleShortcuts',
- 'Shortcut("toggleShowCompleted", "Show/hide completed", "ctrl+o") > .text': 'toggleShowCompleted',
- 'Shortcut("search", "Not Done - Search", "esc") > .text': 'search',
+ 'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+shift+/") body': 'toggleShortcuts',
+ 'Shortcut("toggleShowCompleted", "Show/hide completed", "ctrl+o") body': 'toggleShowCompleted',
+ 'Shortcut("search", "Not Done - Search", "esc") body': 'search',
+ 'Shortcut("undo", "Undo", "ctrl+z") body': 'undo',
+ 'Shortcut("redo", "Redo", "ctrl+shift+z,ctrl+y") body': 'redo',
},
initialize: function(options) {
options = _.defaults({}, options, appDefaults);
e.save();
});
});
- Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right'] });
+ Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right', 'undo', 'redo'] });
this.views = {}; // A list of views for each element in the collection
- this.history = [];
- this.history.redo = [];
+ Actions.App = this;
+ this.undoRedoHistory = {undo: [], redo:[]}; // Linear zipper
this.list.fetch();
this.render();
},
}
},
act: function(action) {
- action.apply();
- this.history.push(action);
- this.history.redo = [];
+ var retVal = action.apply();
+ this.undoRedoHistory.undo.push(action);
+ this.undoRedoHistory.redo = [];
+ return retVal;
},
undo: function() {
- var action = this.history.pop();
- if (!action) throw "Rewind called with empty history stack";
- action.rewind();
- this.history.redo.push(action);
+ var action = this.undoRedoHistory.undo.pop();
+ if (!action) {
+ console.log("Rewind called with empty history stack");
+ return;
+ }
+ var retVal = action.rewind();
+ this.undoRedoHistory.redo.push(action);
+ return retVal;
},
redo: function() {
- var action = this.history.redo.pop();
- if (!action) throw "Replay called with empty redo stack";
+ var action = this.undoRedoHistory.redo.pop();
+ if (!action) {
+ console.log("Replay called with empty redo stack");
+ return;
+ }
action.reapply();
- this.history.push(action);
+ this.undoRedoHistory.undo.push(action);
},
toggleShortcuts: function() {
this.$(".shortcuts").toggle();
Actions = {};
-Actions.AppendWords = function(array, word) {
- this.array = array;
- this.word = word;
+Actions.MoveBullet = function(bullet, newLocation) {
+ this.bullet = bullet;
+ this.oldLocation = bullet.getLocation();
+ this.newLocation = newLocation;
};
-Actions.AppendWords.prototype = _.extend(new BaseAction(), {
+Actions.MoveBullet.prototype = _.extend(new BaseAction(), {
apply: function() {
- this.array.push(this.word);
+ return this.bullet._moveTo(this.newLocation);
},
rewind: function() {
- var a = this.array.pop();
- if (a !== this.word) {
- throw "Rewind faiiiiiled :(";
- }
+ return this.bullet._moveTo(this.oldLocation);
+ },
+});
+
+Actions.ChangeText = function(bullet, newText) {
+ this.bullet = bullet;
+ this.oldText = bullet.get("text");
+ this.newText = newText;
+};
+Actions.ChangeText.prototype = _.extend(new BaseAction(), {
+ apply: function() {
+ return this.bullet._setText(this.newText);
+ },
+ rewind: function() {
+ return this.bullet._setText(this.oldText);
},
});
var el = this.el;
if (objectType === "global") {
Shortcut.globalObject = el;
+ Shortcut.globalObject.options = { view: this };
this._shortcutObject = Shortcut.globalObject;
} else {
this._shortcutObject = Shortcut.addObject(el, objectType, { view: this });
toggleCollapsed: function() {
this.save({collapsed: !this.get("collapsed")});
},
+ _setText: function(text) {
+ return this.save({text: text});
+ },
setText: function(text) {
- this.save({text: text});
+ return Actions.App.act(new Actions.ChangeText(this, text));
},
hasChildren: function() {
return this.get("bullets").length > 0;
this.set("bullets", bullets);
return this;
},
+ getLocation: function() {
+ return {
+ parent: this.getParent(),
+ index: this.getParent().findChild(this.id),
+ };
+ },
moveTo: function(newLocation) {
if (this.isRoot()) {
console.log("Cannot move root");
return this;
}
- var existingLocation = {
- parent: this.getParent(),
- index: this.getParent().findChild(this.id),
- };
+ var existingLocation = this.getLocation();
newLocation = _.defaults({}, newLocation, existingLocation);
+ return Actions.App.act(new Actions.MoveBullet(this, newLocation));
+ },
+ _moveTo: function(newLocation) {
+ var existingLocation = this.getLocation();
var newChildren;
if (newLocation.parent === existingLocation.parent && newLocation.index === existingLocation.index) {
// No-op
el: $("#todo-app"),
shortcutObject: "global",
events: {
- 'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+shift+/") > .text': 'toggleShortcuts',
- 'Shortcut("toggleShowCompleted", "Show/hide completed", "ctrl+o") > .text': 'toggleShowCompleted',
- 'Shortcut("search", "Not Done - Search", "esc") > .text': 'search',
+ 'Shortcut("toggleShortcuts", "Keyboard Shortcuts", "ctrl+shift+/") body': 'toggleShortcuts',
+ 'Shortcut("toggleShowCompleted", "Show/hide completed", "ctrl+o") body': 'toggleShowCompleted',
+ 'Shortcut("search", "Not Done - Search", "esc") body': 'search',
+ 'Shortcut("undo", "Undo", "ctrl+z") body': 'undo',
+ 'Shortcut("redo", "Redo", "ctrl+shift+z,ctrl+y") body': 'redo',
},
initialize: function(options) {
options = _.defaults({}, options, appDefaults);
e.save();
});
});
- Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right'] });
+ Shortcut.bindShortcutsDisplay(this.$("#shortcuts-wrapper")[0], {allowRebind: true, noDisplay: ['combineNext', 'combinePrevious', 'next', 'previous', 'left', 'right', 'undo', 'redo'] });
this.views = {}; // A list of views for each element in the collection
- this.history = [];
- this.history.redo = [];
+ Actions.App = this;
+ this.undoRedoHistory = {undo: [], redo:[]}; // Linear zipper
this.list.fetch();
this.render();
},
}
},
act: function(action) {
- action.apply();
- this.history.push(action);
- this.history.redo = [];
+ var retVal = action.apply();
+ this.undoRedoHistory.undo.push(action);
+ this.undoRedoHistory.redo = [];
+ return retVal;
},
undo: function() {
- var action = this.history.pop();
- if (!action) throw "Rewind called with empty history stack";
- action.rewind();
- this.history.redo.push(action);
+ var action = this.undoRedoHistory.undo.pop();
+ if (!action) {
+ console.log("Rewind called with empty history stack");
+ return;
+ }
+ var retVal = action.rewind();
+ this.undoRedoHistory.redo.push(action);
+ return retVal;
},
redo: function() {
- var action = this.history.redo.pop();
- if (!action) throw "Replay called with empty redo stack";
+ var action = this.undoRedoHistory.redo.pop();
+ if (!action) {
+ console.log("Replay called with empty redo stack");
+ return;
+ }
action.reapply();
- this.history.push(action);
+ this.undoRedoHistory.undo.push(action);
},
toggleShortcuts: function() {
this.$(".shortcuts").toggle();