如何与浏览器控件+ z / control + y进行交互以进行撤消/重做?

时间:2014-06-16 20:19:09

标签: javascript

我正在创建自己的编辑器,我终于解决了几周来一直躲着的撤销/重做问题。

我已经创建了用于存储和遍历自定义操作历史记录的基础框架,但我似乎无法找到有关如何与contentEditable区域中的 browsers 历史记录进行交互的良好信息

https://github.com/jzaefferer/undo/blob/master/undo.js,我仍然看不出这是怎么回事。

我可以撤消/重做我的自定义操作,但我忘记了如何使用浏览器默认历史记录。

如果我要覆盖默认的控件+(z | y) <我是否必须添加原始功能的全部 / p>

更新:在哪里可以找到有关浏览器如何处理这些撤消/重做操作的更多信息?

3 个答案:

答案 0 :(得分:3)

查看可信的demo的来源,以了解更多关于他如何将图书馆附加到div的信息。

$(function() {
    var stack = new Undo.Stack(),
        EditCommand = Undo.Command.extend({
            constructor: function(textarea, oldValue, newValue) {
                this.textarea = textarea;
                this.oldValue = oldValue;
                this.newValue = newValue;
            },
            execute: function() {
            },
            undo: function() {
                this.textarea.html(this.oldValue);
            },

            redo: function() {
                this.textarea.html(this.newValue);
            }
        });
    stack.changed = function() {
        stackUI();
    };

    var undo = $(".undo"),
        redo = $(".redo"),
        dirty = $(".dirty");
    function stackUI() {
        undo.attr("disabled", !stack.canUndo());
        redo.attr("disabled", !stack.canRedo());
        dirty.toggle(stack.dirty());
    }
    stackUI();

    $(document.body).delegate(".undo, .redo, .save", "click", function() {
        var what = $(this).attr("class");
        stack[what]();
        return false;
    });

    var text = $("#text"),
        startValue = text.html(),
        timer;
    $("#text").bind("keyup", function() {
        // a way too simple algorithm in place of single-character undo
        clearTimeout(timer);
        timer = setTimeout(function() {
            var newValue = text.html();
            // ignore meta key presses
            if (newValue != startValue) {
                // this could try and make a diff instead of storing snapshots
                stack.execute(new EditCommand(text, startValue, newValue));
                startValue = newValue;
            }
        }, 250);
    });

    $(".bold").click(function() {
        document.execCommand("bold", false);
        var newValue = text.html(); 
        stack.execute(new EditCommand(text, startValue, newValue));
        startValue = newValue;
    });

            // This is where he attaches the observer for undo / redo.
            // For more information: https://stackoverflow.com/questions/16006583/capturing-ctrlz-key-combination-in-javascript
    $(document).keydown(function(event) {
        if (!event.metaKey || event.keyCode != 90) {
            return;
        }
        event.preventDefault();
        if (event.shiftKey) {
            stack.canRedo() && stack.redo()
        } else {
            stack.canUndo() && stack.undo();
        }
    });
});

Capturing ctrl+z key combination in javascript

答案 1 :(得分:2)

使用此选项,但它仅适用于<div contentEditable="true">个框。在textarea中,它会立即撤消和重做所有文本,而不是像div一样逐字。

<script language="JavaScript">
function Undo() { document.execCommand("undo", false, null); }
function Redo() { document.execCommand("redo", false, null); }
</script>

<div contentEditable="true" style="background-color:rgba(0,0,0,0.8); resize:none; width: 499px; height: 230px; border: 1px solid red;"></div>
<input type="button" onmouseup="Undo()" value="Undo" />
<input type="button" onmouseup="Redo()" value="Redo" />

答案 2 :(得分:1)

我不相信无论如何都要直接访问撤消缓冲区的内容,但您可以使用document.execCommand触发撤消或重做。简单的例子:

<html>
<head>
<style>
  #box {
    width: 200px;
    height: 100px;
    background-color: grey;
  }
</style>
</head>
<body>
  <div id="box" contenteditable="true"></div>
  <button id="undo">Undo</button>
  <button id="redo">Redo</button>
<script>
  var box = document.getElementById('box');
  var undo = document.getElementById('undo');
  var redo = document.getElementById('redo');

  undo.addEventListener('click', function (ev) {
    document.execCommand('undo', false, null);
  });

  redo.addEventListener('click', function (ev) {
    document.execCommand('redo', false, null);
  });
</script>
</body>
</html>

将其视为jsfiddle