Skip to content

Instantly share code, notes, and snippets.

@yckart
Forked from 140bytes/LICENSE.txt
Last active March 8, 2018 11:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yckart/7358468 to your computer and use it in GitHub Desktop.
Save yckart/7358468 to your computer and use it in GitHub Desktop.
undo/redo manager

Undo and redo is a fairly interesting and surprisingly difficult concept to implement in an application. Thanks to the way javascript treats functions, it isn't too hard to come up with a general and powerful approach for javascript apps.

undone([
  function () {
    // undo
  },
  function () {
    // redo
  }
]);

undone(0); // => undo
undone(1); // => redo
function (a, b) {
a = [
[], // undo stack
[] // redo stack
];
return function (c) {
// it's an array
c[0] ? (
// reset the redo stack
a[1] = [],
// add the action to our undo stack
a[0].push(c),
// call the undo function
c[0]()
) : (
b = a[c] // assign undo/redo stack
.pop() // and remove last stack from it
// if it doesn't exist, stop here
) && (
a[+!c] // negate `c`
.push(b), // push the negated stack to its complementary stack
b[+!c]() // call it
)
}
}()
function(a,b){a=[[],[]];return function(c){c[0]?(a[1]=[],a[0].push(c),c[0]()):(b=a[c].pop())&&(a[+!c].push(b),b[+!c]())}}()
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 YOUR_NAME_HERE <YOUR_URL_HERE>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "undo / redo manager",
"description": "A really simple command stack, with undo/redo functionality.",
"keywords": [
"undo",
"redo",
"command",
"stack",
"function"
]
}
<!DOCTYPE html>
<title>Foo</title>
<div>CTRL + Z: <b>undo</b></div>
<div>CTRL + Y: <b>redo</b></div>
<script>
var undone = function(a,b){a=[[],[]];return function(c){c[0]?(a[1]=[],a[0].push(c),c[0]()):(b=a[c].pop())&&(a[+!c].push(b),b[+!c]())}}()
var css = function (elem, prop, value) {
var redo = elem.style[prop];
undone([
// undo
function () {
elem.style[prop] = value;
},
// redo
function () {
elem.style[prop] = redo;
}
]);
};
var body = document.body;
css(body, 'background', 'gold');
css(body, 'background', 'tomato');
css(body, 'background', 'yellowgreen');
css(body, 'background', 'darkturquoise');
document.onkeydown = function (e) {
if (!e.ctrlKey || e.which < 89 || e.which > 90) return;
undone(90 - e.which);
};
</script>
@atk
Copy link

atk commented Nov 8, 2013

if-else shorthand ?: can be used to shave 7 bytes off this one:

function(a,b){a=[[],[]];return function(d){d[0]?(a[1]=[],a[0].push(d),d[0]()):(b=a[d].pop())&&(a[+!d].push(b),b[+!d]())}}()

@yckart
Copy link
Author

yckart commented Nov 8, 2013

@atk Ah, good point! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment