commandz 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +137 -18
- data/commandz.min.js +3 -3
- data/lib/assets/javascripts/commandz.coffee +80 -30
- data/lib/commandz/version.rb +1 -1
- data/spec/commandz_spec.coffee +91 -21
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 706f3e28800a1bd1c1e659a2fcf7a355c8b03fab
|
4
|
+
data.tar.gz: 4b3451066e237bbf6e4c75e8245f9ac1e528a490
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2caf799f9bab92f94978984affae1337d23acb9dba7f4476d3a55637a5ed810e60d08ce08ba4c708b7251f0d5df24e65c2b6ea61f4bf43d69891bf9850ecb35
|
7
|
+
data.tar.gz: aa1ddb7d6a90db28f177d10b24eac586e94dfc16eea054ed29aa372d30d3d9dbdf609e8a9a5c42f03ee44079991efa6737f6840372f185814d858d5b011951aa
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## [v0.1.0](https://github.com/EtienneLem/commandz/tree/v0.1.0)
|
2
|
+
- Rename `CommandZ.commands` -> `CommandZ.history`
|
3
|
+
- Rename `CommandZ.onChange` -> `CommandZ.onStatusChange`
|
4
|
+
- Add storage with threshold support
|
5
|
+
- Add `CommandZ.reset()`
|
6
|
+
|
1
7
|
## [v0.0.3](https://github.com/EtienneLem/commandz/tree/v0.0.3)
|
2
8
|
- Fix a bug where `handleChange` wouldn’t be called after `CommandZ.execute()`
|
3
9
|
|
data/README.md
CHANGED
@@ -16,14 +16,19 @@
|
|
16
16
|
|
17
17
|
## Table of contents
|
18
18
|
- [API](#api)
|
19
|
-
- [
|
20
|
-
- [
|
21
|
-
- [
|
22
|
-
- [
|
23
|
-
- [
|
24
|
-
- [
|
25
|
-
- [
|
19
|
+
- [execute](#execute) | [store](#store)
|
20
|
+
- [undo (commands)](#undo-commands) | [undo (storage)](#undo-storage)
|
21
|
+
- [redo (commands)](#redo-commands) | [redo (storage)](#redo-storage)
|
22
|
+
- [setThreshold (storage only)](#setthreshold-storage-only)
|
23
|
+
- [status](#status)
|
24
|
+
- [onStatusChange](#onstatuschange)
|
25
|
+
- [onStorageChange](#onstoragechange)
|
26
|
+
- [clear](#clear)
|
27
|
+
- [reset](#reset)
|
28
|
+
- [keyboardShortcuts](#keyboardshortcuts)
|
26
29
|
- [DOM Example](#dom-example)
|
30
|
+
- [Commands](#commands)
|
31
|
+
- [Storage](#storage)
|
27
32
|
- [Setup](#setup)
|
28
33
|
- [Rails](#rails)
|
29
34
|
- [Other](#other)
|
@@ -39,8 +44,9 @@ COMMAND: {
|
|
39
44
|
}
|
40
45
|
```
|
41
46
|
|
42
|
-
### execute
|
43
|
-
Receive `COMMAND` or `COMMANDS` and execute `COMMAND.up()
|
47
|
+
### #execute
|
48
|
+
Receive `COMMAND` or `COMMANDS` and execute `COMMAND.up()`.<br>
|
49
|
+
Store commands as a `{ command: COMMAND }` object in the history array.
|
44
50
|
|
45
51
|
**Single command per history item**<br>
|
46
52
|
Store one history item per `COMMAND`.
|
@@ -79,8 +85,8 @@ console.log(CommandZ.commands.length) // => 1
|
|
79
85
|
console.log(CommandZ.index) // => 0
|
80
86
|
```
|
81
87
|
|
82
|
-
### undo
|
83
|
-
Call `COMMAND.down()` and set the index to the previous
|
88
|
+
### #undo (commands)
|
89
|
+
Call `COMMAND.down()` and set the index to the previous history item.
|
84
90
|
|
85
91
|
```js
|
86
92
|
CommandZ.execute({
|
@@ -104,8 +110,8 @@ console.log(CommandZ.commands.length) // => 2
|
|
104
110
|
console.log(CommandZ.index) // => -1
|
105
111
|
```
|
106
112
|
|
107
|
-
### redo
|
108
|
-
Set the index to the next
|
113
|
+
### #redo (commands)
|
114
|
+
Set the index to the next history item and call `COMMAND.up()`.
|
109
115
|
|
110
116
|
```js
|
111
117
|
CommandZ.execute({
|
@@ -125,7 +131,73 @@ console.log(CommandZ.commands.length) // => 2
|
|
125
131
|
console.log(CommandZ.index) // => 0
|
126
132
|
```
|
127
133
|
|
128
|
-
###
|
134
|
+
### #store
|
135
|
+
Store data as a `{ data: … }` object in the history array.
|
136
|
+
|
137
|
+
```js
|
138
|
+
CommandZ.store({ width: 100, height: 100 })
|
139
|
+
```
|
140
|
+
|
141
|
+
### #undo (storage)
|
142
|
+
Set the index to the previous history item and send data via [`CommandZ.onStorageChange`](#onstoragechange).
|
143
|
+
|
144
|
+
```js
|
145
|
+
CommandZ.onStorageChange(function(data) {
|
146
|
+
console.log(data)
|
147
|
+
})
|
148
|
+
|
149
|
+
CommandZ.store({ width: 100, height: 100 })
|
150
|
+
CommandZ.undo()
|
151
|
+
|
152
|
+
console.log(CommandZ.commands.length) // => 1
|
153
|
+
console.log(CommandZ.index) // => -1
|
154
|
+
|
155
|
+
CommandZ.store({ width: 100, height: 100 })
|
156
|
+
CommandZ.store({ width: 200, height: 200 })
|
157
|
+
CommandZ.undo() # => { width: 100, height: 100 }
|
158
|
+
|
159
|
+
console.log(CommandZ.commands.length) // => 2
|
160
|
+
console.log(CommandZ.index) // => 0
|
161
|
+
```
|
162
|
+
|
163
|
+
### #redo (storage)
|
164
|
+
Set the index to the next history item and send data via [`CommandZ.onStorageChange`](#onstoragechange).
|
165
|
+
|
166
|
+
```js
|
167
|
+
CommandZ.onStorageChange(function(data) {
|
168
|
+
console.log(data)
|
169
|
+
})
|
170
|
+
|
171
|
+
CommandZ.store({ width: 100, height: 100 })
|
172
|
+
CommandZ.store({ width: 200, height: 200 })
|
173
|
+
CommandZ.undo() # => { width: 100, height: 100 }
|
174
|
+
CommandZ.redo() # => { width: 200, height: 200 }
|
175
|
+
|
176
|
+
console.log(CommandZ.commands.length) // => 2
|
177
|
+
console.log(CommandZ.index) // => 1
|
178
|
+
```
|
179
|
+
|
180
|
+
### #setThreshold (storage only)
|
181
|
+
Unlike commands, you can allow your users to spam the `CMD+Z` button without restoring every states at every steps.<br>
|
182
|
+
Threshold is set in `milliseconds`.
|
183
|
+
|
184
|
+
```js
|
185
|
+
CommandZ.setThreshold(500)
|
186
|
+
CommandZ.onStorageChange(function(data) {
|
187
|
+
console.log(data)
|
188
|
+
})
|
189
|
+
|
190
|
+
CommandZ.store({ width: 100, height: 100 })
|
191
|
+
CommandZ.store({ width: 200, height: 200 })
|
192
|
+
CommandZ.store({ width: 300, height: 300 })
|
193
|
+
|
194
|
+
CommandZ.undo(100)
|
195
|
+
|
196
|
+
// Wait 500ms
|
197
|
+
// => { width: 100, height: 100 }
|
198
|
+
```
|
199
|
+
|
200
|
+
### #status
|
129
201
|
Return the current status.
|
130
202
|
|
131
203
|
```js
|
@@ -144,11 +216,11 @@ console.log(CommandZ.commands.length) // => 2
|
|
144
216
|
console.log(CommandZ.index) // => 1
|
145
217
|
```
|
146
218
|
|
147
|
-
###
|
219
|
+
### #onStatusChange
|
148
220
|
Register a callback that will be called with the `status` every time there’s a change to the history.
|
149
221
|
|
150
222
|
```js
|
151
|
-
CommandZ.
|
223
|
+
CommandZ.onStatusChange(function(status) {
|
152
224
|
console.log(status)
|
153
225
|
})
|
154
226
|
|
@@ -166,7 +238,21 @@ CommandZ.undo() // => { canUndo: true, canRedo: true }
|
|
166
238
|
CommandZ.undo() // => { canUndo: false, canRedo: true }
|
167
239
|
```
|
168
240
|
|
169
|
-
###
|
241
|
+
### #onStorageChange
|
242
|
+
Register a callback that will be called with the `data` on undo/redo.
|
243
|
+
|
244
|
+
```js
|
245
|
+
CommandZ.onStorageChange(function(data) {
|
246
|
+
console.log(data)
|
247
|
+
})
|
248
|
+
|
249
|
+
CommandZ.store({ width: 100, height: 100 })
|
250
|
+
CommandZ.store({ width: 200, height: 200 })
|
251
|
+
|
252
|
+
CommandZ.undo() // => { width: 100, height: 100 }
|
253
|
+
```
|
254
|
+
|
255
|
+
### #clear
|
170
256
|
Clear history.
|
171
257
|
|
172
258
|
```js
|
@@ -187,7 +273,10 @@ console.log(CommandZ.commands.length) // => 0
|
|
187
273
|
console.log(CommandZ.index) // => -1
|
188
274
|
```
|
189
275
|
|
190
|
-
###
|
276
|
+
### #reset
|
277
|
+
Clear history, remove callbacks and set threshold to 0.
|
278
|
+
|
279
|
+
### #keyboardShortcuts
|
191
280
|
Enable or disable `CMD+Z` & `CMD+SHIFT+Z` keyboard shortcuts. These shortcuts are enabled by default.<br>
|
192
281
|
Will only `undo()` & `redo()` if the current selected element is not an input so that it doesn’t prevent your OS default behavior.
|
193
282
|
|
@@ -197,6 +286,7 @@ CommandZ.keyboardShortcuts(false)
|
|
197
286
|
```
|
198
287
|
|
199
288
|
## DOM Example
|
289
|
+
### Commands
|
200
290
|
```js
|
201
291
|
// This example requires jQuery or Zepto
|
202
292
|
$container = $('<div></div>')
|
@@ -234,6 +324,35 @@ console.log(CommandZ.commands.length) // => 3
|
|
234
324
|
console.log(CommandZ.index) // => 2
|
235
325
|
```
|
236
326
|
|
327
|
+
### Storage
|
328
|
+
```js
|
329
|
+
// This example requires jQuery or Zepto
|
330
|
+
$container = $('<div></div>')
|
331
|
+
|
332
|
+
img = new Image
|
333
|
+
$container.html(img)
|
334
|
+
|
335
|
+
// Register undo/redo callback
|
336
|
+
CommandZ.onStorageChange = function(data) {
|
337
|
+
img.width = data.width
|
338
|
+
img.height = data.height
|
339
|
+
}
|
340
|
+
|
341
|
+
img.width = 100
|
342
|
+
img.height = 100
|
343
|
+
|
344
|
+
// Lets store some states
|
345
|
+
[1, 2, 3, 4].forEach(function(i) {
|
346
|
+
CommandZ.store({ width: i * 100, height: i * 100 })
|
347
|
+
})
|
348
|
+
|
349
|
+
CommandZ.undo(2)
|
350
|
+
console.log(img.width) // => 200
|
351
|
+
|
352
|
+
CommandZ.redo()
|
353
|
+
console.log(img.width) // => 300
|
354
|
+
```
|
355
|
+
|
237
356
|
## Setup
|
238
357
|
### Rails
|
239
358
|
1. Add `gem 'commandz'` to your Gemfile.
|
data/commandz.min.js
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
/*
|
2
|
-
* CommandZ v0.0
|
2
|
+
* CommandZ v0.1.0
|
3
3
|
* https://github.com/EtienneLem/commandz
|
4
4
|
*
|
5
5
|
* Copyright 2013, Etienne Lemay http://heliom.ca
|
6
6
|
* Released under the MIT license
|
7
7
|
*
|
8
|
-
* Date: 2013-
|
8
|
+
* Date: 2013-09-02 11:47:04 -0400
|
9
9
|
*/
|
10
|
-
(function(){var t,
|
10
|
+
(function(){var t,e=function(t,e){return function(){return t.apply(e,arguments)}};t=function(){function t(){this.handleKeypress=e(this.handleKeypress,this),this.VERSION="0.1.0",this.reset(),this.keyboardShortcuts(!0)}return t.prototype.reset=function(){return this.clear(),this.statusChangeCallback=null,this.storageChangeCallback=null,this.thresholdTimer=null,this.threshold=0},t.prototype.clear=function(){return this.history=[],this.index=-1},t.prototype.keyboardShortcuts=function(t){var e;return null==t&&(t=!0),e=t?"addEventListener":"removeEventListener",document[e]("keypress",this.handleKeypress)},t.prototype.handleKeypress=function(t){return"INPUT"!==document.activeElement.nodeName&&122===t.keyCode&&t.metaKey===!0?(t.preventDefault(),t.shiftKey?this.redo():this.undo()):void 0},t.prototype.execute=function(t){var e;return e={},e.command=t,this.up(t),this.addToHistory(e)},t.prototype.store=function(t){var e;return e={},e.data=t,this.addToHistory(e)},t.prototype.addToHistory=function(t){var e;return this.index<this.history.length-1&&(e=this.history.length-this.index-1,this.history.splice(-e)),this.history.push(t),this.index=this.history.length-1,this.handleStatusChange()},t.prototype.undo=function(t){var e,n,s,i,h;if(null==t&&(t=1),this.status().canUndo)for(i=h=1;t>=1?t>=h:h>=t;i=t>=1?++h:--h){if(!this.history[this.index])return;s=this.history[this.index],(e=s.command)&&this.down(e),this.index--,(s=this.history[this.index])&&(n=s.data)&&this.handleData(n),this.handleStatusChange()}},t.prototype.redo=function(t){var e,n,s,i,h;if(null==t&&(t=1),this.status().canRedo)for(i=h=1;t>=1?t>=h:h>=t;i=t>=1?++h:--h){if(!this.history[this.index+1])return;this.index++,s=this.history[this.index],(e=s.command)&&this.up(e),(n=s.data)&&this.handleData(n),this.handleStatusChange()}},t.prototype.exec=function(t,e){var n,s,i,h;if(!(e instanceof Array))return e[t]();for(h=[],s=0,i=e.length;i>s;s++)n=e[s],h.push(n[t]());return h},t.prototype.up=function(t){return this.exec("up",t)},t.prototype.down=function(t){return this.exec("down",t)},t.prototype.handleData=function(t){var e=this;return this.threshold>0?(clearTimeout(this.thresholdTimer),this.thresholdTimer=setTimeout(function(){return e.sendData(t)},this.threshold)):this.sendData(t)},t.prototype.sendData=function(t){return this.storageChangeCallback?this.storageChangeCallback(t):void 0},t.prototype.onStorageChange=function(t){return this.storageChangeCallback=t},t.prototype.setThreshold=function(t){return this.threshold=t},t.prototype.onStatusChange=function(t){return this.statusChangeCallback=t,this.handleStatusChange()},t.prototype.handleStatusChange=function(){return this.statusChangeCallback?this.statusChangeCallback(this.status()):void 0},t.prototype.status=function(){return{canUndo:this.index>-1,canRedo:this.index<this.history.length-1}},t}(),this.CommandZ=new t}).call(this);
|
@@ -1,63 +1,94 @@
|
|
1
1
|
class CommandZ
|
2
2
|
|
3
3
|
constructor: ->
|
4
|
-
@VERSION = '0.0
|
5
|
-
@changeCallback = null
|
4
|
+
@VERSION = '0.1.0'
|
6
5
|
|
7
|
-
this.
|
6
|
+
this.reset()
|
8
7
|
this.keyboardShortcuts(true)
|
9
8
|
|
9
|
+
reset: ->
|
10
|
+
this.clear()
|
11
|
+
|
12
|
+
@statusChangeCallback = null
|
13
|
+
@storageChangeCallback = null
|
14
|
+
@thresholdTimer = null
|
15
|
+
@threshold = 0
|
16
|
+
|
10
17
|
clear: ->
|
11
|
-
@
|
18
|
+
@history = []
|
12
19
|
@index = -1
|
13
20
|
|
14
21
|
keyboardShortcuts: (enable=true) ->
|
15
22
|
addOrRemove = if enable then 'addEventListener' else 'removeEventListener'
|
16
|
-
document[addOrRemove]('keypress', this.
|
23
|
+
document[addOrRemove]('keypress', this.handleKeypress)
|
17
24
|
|
18
|
-
|
25
|
+
handleKeypress: (e) =>
|
19
26
|
return if document.activeElement.nodeName is 'INPUT'
|
20
27
|
return unless e.keyCode is 122 and e.metaKey is true
|
21
28
|
|
22
29
|
e.preventDefault()
|
23
30
|
if e.shiftKey then this.redo() else this.undo()
|
24
31
|
|
32
|
+
# Execute and store commands as { command: {up: ->, down: ->} }
|
25
33
|
execute: (command) ->
|
34
|
+
historyItem = {}
|
35
|
+
historyItem.command = command
|
36
|
+
|
26
37
|
this.up(command)
|
38
|
+
this.addToHistory(historyItem)
|
39
|
+
|
40
|
+
# Store data as { data: … }
|
41
|
+
store: (data) ->
|
42
|
+
historyItem = {}
|
43
|
+
historyItem.data = data
|
44
|
+
|
45
|
+
this.addToHistory(historyItem)
|
46
|
+
|
47
|
+
# History management
|
48
|
+
addToHistory: (historyItem) ->
|
49
|
+
# Overwrite upcoming history items
|
50
|
+
if @index < @history.length - 1
|
51
|
+
difference = (@history.length - @index) - 1
|
52
|
+
@history.splice(-difference)
|
27
53
|
|
28
|
-
|
29
|
-
|
30
|
-
difference = (@commands.length - @index) - 1
|
31
|
-
@commands.splice(-difference)
|
54
|
+
@history.push(historyItem)
|
55
|
+
@index = @history.length - 1
|
32
56
|
|
33
|
-
|
34
|
-
@commands.push(command)
|
35
|
-
@index = @commands.length - 1
|
36
|
-
this.handleChange()
|
57
|
+
this.handleStatusChange()
|
37
58
|
|
38
59
|
undo: (times=1) ->
|
39
60
|
return unless this.status().canUndo
|
40
61
|
|
41
62
|
for i in [1..times]
|
42
|
-
return unless @
|
63
|
+
return unless @history[@index]
|
43
64
|
|
44
|
-
|
65
|
+
historyItem = @history[@index]
|
66
|
+
this.down(command) if command = historyItem.command
|
67
|
+
|
68
|
+
# Has to be after a command item, but before a data item
|
45
69
|
@index--
|
46
70
|
|
47
|
-
|
71
|
+
if historyItem = @history[@index]
|
72
|
+
this.handleData(data) if data = historyItem.data
|
73
|
+
|
74
|
+
this.handleStatusChange()
|
48
75
|
|
49
76
|
redo: (times=1) ->
|
50
77
|
return unless this.status().canRedo
|
51
78
|
|
52
79
|
for i in [1..times]
|
53
|
-
return unless @
|
80
|
+
return unless @history[@index + 1]
|
54
81
|
|
82
|
+
# Has to be before both a command and a data item
|
55
83
|
@index++
|
56
|
-
this.up(@commands[@index])
|
57
84
|
|
58
|
-
|
85
|
+
historyItem = @history[@index]
|
86
|
+
this.up(command) if command = historyItem.command
|
87
|
+
this.handleData(data) if data = historyItem.data
|
59
88
|
|
60
|
-
|
89
|
+
this.handleStatusChange()
|
90
|
+
|
91
|
+
# Execute up/down action on a command
|
61
92
|
# command can be a group of commands or a single command
|
62
93
|
exec: (action, command) ->
|
63
94
|
return command[action]() unless command instanceof Array
|
@@ -66,19 +97,38 @@ class CommandZ
|
|
66
97
|
up: (command) -> this.exec('up', command)
|
67
98
|
down: (command) -> this.exec('down', command)
|
68
99
|
|
69
|
-
#
|
70
|
-
|
71
|
-
@
|
72
|
-
|
100
|
+
# Send current history item data
|
101
|
+
handleData: (data) ->
|
102
|
+
return this.sendData(data) unless @threshold > 0
|
103
|
+
|
104
|
+
clearTimeout(@thresholdTimer)
|
105
|
+
@thresholdTimer = setTimeout =>
|
106
|
+
this.sendData(data)
|
107
|
+
, @threshold
|
108
|
+
|
109
|
+
sendData: (data) ->
|
110
|
+
return unless @storageChangeCallback
|
111
|
+
@storageChangeCallback(data)
|
112
|
+
|
113
|
+
# Storage management
|
114
|
+
onStorageChange: (callback) ->
|
115
|
+
@storageChangeCallback = callback
|
116
|
+
|
117
|
+
setThreshold: (threshold) ->
|
118
|
+
@threshold = threshold
|
119
|
+
|
120
|
+
# Status management
|
121
|
+
onStatusChange: (callback) ->
|
122
|
+
@statusChangeCallback = callback
|
123
|
+
this.handleStatusChange()
|
73
124
|
|
74
|
-
|
75
|
-
return unless @
|
76
|
-
@
|
125
|
+
handleStatusChange: ->
|
126
|
+
return unless @statusChangeCallback
|
127
|
+
@statusChangeCallback(this.status())
|
77
128
|
|
78
|
-
# Return current status
|
79
129
|
status: ->
|
80
130
|
canUndo: @index > -1
|
81
|
-
canRedo: @index < @
|
131
|
+
canRedo: @index < @history.length - 1
|
82
132
|
|
83
133
|
# Singleton
|
84
134
|
@CommandZ = new CommandZ
|
data/lib/commandz/version.rb
CHANGED
data/spec/commandz_spec.coffee
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
describe 'CommandZ', ->
|
2
|
-
describe '
|
2
|
+
describe 'commands', ->
|
3
3
|
it 'stores commands', ->
|
4
4
|
[0..9].forEach (i) -> CommandZ.execute({up: (-> i), down: (-> i)})
|
5
5
|
|
6
|
-
expect(CommandZ.
|
6
|
+
expect(CommandZ.history.length).toBe(10)
|
7
7
|
expect(CommandZ.index).toBe(9)
|
8
8
|
|
9
9
|
it 'undo', ->
|
10
10
|
[0..3].forEach -> CommandZ.undo()
|
11
11
|
|
12
|
-
expect(CommandZ.
|
12
|
+
expect(CommandZ.history.length).toBe(10)
|
13
13
|
expect(CommandZ.index).toBe(5)
|
14
14
|
|
15
15
|
it 'redo', ->
|
16
16
|
CommandZ.redo()
|
17
17
|
|
18
|
-
expect(CommandZ.
|
18
|
+
expect(CommandZ.history.length).toBe(10)
|
19
19
|
expect(CommandZ.index).toBe(6)
|
20
20
|
|
21
21
|
it 'undo many times', ->
|
22
22
|
CommandZ.undo(3)
|
23
|
-
expect(CommandZ.
|
23
|
+
expect(CommandZ.history.length).toBe(10)
|
24
24
|
expect(CommandZ.index).toBe(3)
|
25
25
|
|
26
26
|
CommandZ.undo(100)
|
27
|
-
expect(CommandZ.
|
27
|
+
expect(CommandZ.history.length).toBe(10)
|
28
28
|
expect(CommandZ.index).toBe(-1)
|
29
29
|
|
30
30
|
it 'redo many times', ->
|
31
31
|
CommandZ.redo(3)
|
32
|
-
expect(CommandZ.
|
32
|
+
expect(CommandZ.history.length).toBe(10)
|
33
33
|
expect(CommandZ.index).toBe(2)
|
34
34
|
|
35
35
|
CommandZ.redo(100)
|
36
|
-
expect(CommandZ.
|
36
|
+
expect(CommandZ.history.length).toBe(10)
|
37
37
|
expect(CommandZ.index).toBe(9)
|
38
38
|
|
39
39
|
it 'returns current status', ->
|
@@ -46,47 +46,92 @@ describe 'CommandZ', ->
|
|
46
46
|
CommandZ.undo(3)
|
47
47
|
CommandZ.execute({up: (->), down: (->)})
|
48
48
|
|
49
|
-
expect(CommandZ.
|
49
|
+
expect(CommandZ.history.length).toBe(8)
|
50
50
|
expect(CommandZ.index).toBe(7)
|
51
51
|
|
52
52
|
it 'clears commands', ->
|
53
53
|
CommandZ.clear()
|
54
54
|
|
55
|
-
expect(CommandZ.
|
55
|
+
expect(CommandZ.history.length).toBe(0)
|
56
56
|
expect(CommandZ.index).toBe(-1)
|
57
57
|
|
58
58
|
it 'stores grouped commands', ->
|
59
59
|
CommandZ.execute([{up: (->), down: (->)}, {up: (->), down: (->)}])
|
60
|
-
CommandZ.undo()
|
61
|
-
CommandZ.redo()
|
62
60
|
|
63
|
-
expect(CommandZ.
|
64
|
-
expect(CommandZ.
|
61
|
+
expect(CommandZ.history.length).toBe(1)
|
62
|
+
expect(CommandZ.history[0].command.length).toBe(2)
|
65
63
|
|
66
64
|
expect(CommandZ.index).toBe(0)
|
67
65
|
|
68
|
-
it 'registers
|
66
|
+
it 'registers onStatusChange callback', ->
|
69
67
|
CommandZ.clear()
|
70
68
|
[0..2].forEach (i) -> CommandZ.execute({up: (-> i), down: (-> i)})
|
71
69
|
|
72
|
-
|
73
|
-
CommandZ.
|
70
|
+
onStatusChangeCallback = jasmine.createSpy('onStatusChangeCallback')
|
71
|
+
CommandZ.onStatusChange (status) -> onStatusChangeCallback('test')
|
74
72
|
|
75
73
|
CommandZ.undo(3)
|
76
74
|
CommandZ.redo(2)
|
77
75
|
CommandZ.execute({up: (->), down: (->)})
|
78
76
|
|
79
|
-
expect(
|
80
|
-
CommandZ.
|
77
|
+
expect(onStatusChangeCallback.calls.length).toBe(7)
|
78
|
+
CommandZ.onStatusChange(null)
|
79
|
+
|
80
|
+
describe 'storage', ->
|
81
|
+
data = null
|
82
|
+
|
83
|
+
beforeEach ->
|
84
|
+
CommandZ.reset()
|
85
|
+
[1..3].forEach (i) -> CommandZ.store({ width: i * 100, height: i * 100 })
|
86
|
+
|
87
|
+
it 'stores data', ->
|
88
|
+
expect(CommandZ.history.length).toBe(3)
|
89
|
+
expect(CommandZ.index).toBe(2)
|
90
|
+
|
91
|
+
it 'undo', ->
|
92
|
+
CommandZ.onStorageChange (storageData) -> data = storageData
|
93
|
+
CommandZ.undo()
|
94
|
+
|
95
|
+
expect(data).toEqual({ width: 200, height: 200 })
|
96
|
+
|
97
|
+
it 'redo', ->
|
98
|
+
CommandZ.undo()
|
99
|
+
CommandZ.onStorageChange (storageData) -> data = storageData
|
100
|
+
CommandZ.redo()
|
101
|
+
|
102
|
+
expect(data).toEqual({ width: 300, height: 300 })
|
103
|
+
|
104
|
+
it 'undo and redo many times', ->
|
105
|
+
spyOn(CommandZ, 'sendData')
|
106
|
+
|
107
|
+
CommandZ.undo(2)
|
108
|
+
CommandZ.redo(2)
|
109
|
+
expect(CommandZ.sendData.calls.length).toBe(4)
|
110
|
+
|
111
|
+
CommandZ.redo(100)
|
112
|
+
expect(CommandZ.sendData.calls.length).toBe(4)
|
113
|
+
|
114
|
+
it 'has a threshold', ->
|
115
|
+
spyOn(CommandZ, 'sendData')
|
116
|
+
|
117
|
+
CommandZ.setThreshold(500)
|
118
|
+
CommandZ.undo(100)
|
119
|
+
|
120
|
+
waits(450)
|
121
|
+
runs -> expect(CommandZ.sendData.calls.length).toBe(0)
|
122
|
+
|
123
|
+
waits(100)
|
124
|
+
runs -> expect(CommandZ.sendData.calls.length).toBe(1)
|
81
125
|
|
82
126
|
describe 'integration', ->
|
83
127
|
$container = null
|
84
128
|
|
85
129
|
beforeEach ->
|
86
|
-
CommandZ.
|
87
|
-
loadFixtures('spec_container.html')
|
130
|
+
CommandZ.reset()
|
88
131
|
|
132
|
+
loadFixtures('spec_container.html')
|
89
133
|
$container = $('#spec-container')
|
134
|
+
|
90
135
|
[0..4].forEach ->
|
91
136
|
$test = $('<div class="foo"></div>')
|
92
137
|
CommandZ.execute
|
@@ -132,3 +177,28 @@ describe 'CommandZ', ->
|
|
132
177
|
|
133
178
|
CommandZ.undo()
|
134
179
|
expect($container.html()).toBe('')
|
180
|
+
|
181
|
+
it 'restores states with stored data', ->
|
182
|
+
img = new Image
|
183
|
+
$container.html(img)
|
184
|
+
|
185
|
+
CommandZ.onStorageChange (data) ->
|
186
|
+
img.width = data.width
|
187
|
+
img.height = data.height
|
188
|
+
|
189
|
+
img.width = 100
|
190
|
+
img.height = 100
|
191
|
+
|
192
|
+
[1..4].forEach (i) -> CommandZ.store({ width: i * 100, height: i * 100 })
|
193
|
+
|
194
|
+
CommandZ.undo(2)
|
195
|
+
expect(img.width).toBe(200)
|
196
|
+
|
197
|
+
CommandZ.redo()
|
198
|
+
expect(img.width).toBe(300)
|
199
|
+
|
200
|
+
CommandZ.redo(100)
|
201
|
+
expect(img.width).toBe(400)
|
202
|
+
|
203
|
+
CommandZ.undo(100)
|
204
|
+
expect(img.width).toBe(100)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: commandz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Etienne Lemay
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|