This repository has been archived by the owner on May 21, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
regrettable.coffee
91 lines (74 loc) · 2.25 KB
/
regrettable.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
_ = if require? then require("underscore") else window._
Backbone = if require? then require("backbone") else window.Backbone
class Action
constructor: ->
undo: ->
redo: ->
class CollectionAddAction extends Action
constructor: (@collection, @model) ->
undo: -> @collection.remove(@model)
redo: -> @collection.add(@model)
class CollectionRemoveAction extends Action
constructor: (@collection, @model) ->
undo: -> @collection.add(@model)
redo: -> @collection.remove(@model)
class ModelPropertyUpdateAction extends Action
constructor: (@model, @prop, @newVal, @oldVal ) ->
undo: -> @model.set(@prop, @oldVal)
redo: -> @model.set(@prop, @newVal)
class ModelUpdateAction extends Action
constructor: (@model) ->
@actions = []
for attr, newVal of @model.changedAttributes()
@actions.push(new ModelPropertyUpdateAction(@model, attr, newVal, @model.previous(attr)))
undo: -> _.invoke @actions, 'undo'
redo: -> _.invoke @actions, 'redo'
Backbone.Regrettable = (->
undoStack = []
redoStack = []
tracking = true
undoStack: -> undoStack
redoStack: -> redoStack
tracking: (t)->
tracking = t
undo: ->
return if undoStack.length == 0
try
tracking = false
action = undoStack.pop()
action.undo()
redoStack.push(action)
finally
tracking = true
redo: ->
return if redoStack.length == 0
try
tracking = false
action = redoStack.pop()
action.redo()
undoStack.push(action)
finally
tracking = true
hasUndo: ->
return undoStack.length > 0
hasRedo: ->
return redoStack.length > 0
reset: ->
undoStack = []
redoStack = []
bind: (o) ->
if o instanceof Backbone.Model
o.on "change", (model) ->
undoStack.push(new ModelUpdateAction(model)) if tracking
else if o instanceof Backbone.Collection
o.on "add", (prod) ->
undoStack.push(new CollectionAddAction(o, prod)) if tracking
o.on "remove", (prod) ->
undoStack.push(new CollectionRemoveAction(o, prod)) if tracking
)()
if module?.exports?
_.extend Backbone.Regrettable,
CollectionAddAction: CollectionAddAction
CollectionRemoveAction: CollectionRemoveAction
ModelUpdateAction: ModelUpdateAction
module.exports = Backbone.Regrettable