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

Posted

技术标签:

【中文标题】如何与浏览器 control+z/control+y 交互以进行撤消/重做?【英文标题】:How can I interact with browser control+z/control+y for undo/redo? 【发布时间】:2014-08-06 17:47:16 【问题描述】:

我正在创建自己的编辑器,并且终于解决了我已经躲避了数周的撤消/重做问题。

我已经创建了用于存储和遍历自定义操作历史的基本框架,但我似乎无法在 contentEditable 区域中找到有关如何与 浏览器 历史交互的良好信息。

看https://github.com/jzaefferer/undo/blob/master/undo.js,还是没看出来这是怎么做到的。

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

如果我要覆盖默认的control + (z | y),我是否必须添加所有原始功能?

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

【问题讨论】:

你是指他们访问过的页面? 您没有必须这样做,只要确保您对删除部分默认功能会产生的可用性问题感到满意。 这与页面历史无关.. html5 contentEditable 历史.. 正在输入的文本,execCommand 等。@blgt 有没有办法让 2 简单地共存?如果我能找到有关其工作原理的资源,我会更好地了解可以做什么和不可以做什么。 我见过的大多数情况只是使用了浏览器内置的撤消/重做功能。为什么需要特殊功能来处理自定义操作? 7 年...没有答案(顺便说一句,问题是实际的) 【参考方案1】:

查看 contenteditable 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://***.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

【讨论】:

【参考方案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" />

【讨论】:

【参考方案3】:

我不相信直接访问撤消缓冲区的内容,但您可以使用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。

【讨论】:

这对我的情况没有帮助。我知道我可以为execCommand 函数执行此操作,但是诸如键入的文本之类的内容超出了此答案的范围。默认的撤消/重做不仅仅是粗体/取消粗体等。我只需要它做更多更多,并与我的自定义操作共存。看来我必须“破解”默认功能并完全覆盖它.. 我认为你应该澄清一下你的问题。您的问题似乎是关于如何访问默认的撤消/重做功能,即使在覆盖典型的(ctrl-c/z)快捷方式时也是如此。如果您解释了您想要完成的工作,这将有所帮助。您需要的更多功能是什么?我认为这个问题有一个XY Problem。

以上是关于如何与浏览器 control+z/control+y 交互以进行撤消/重做?的主要内容,如果未能解决你的问题,请参考以下文章

CORS“Access-Control-Allow-Origin”值如何暴露给浏览器?

打开浏览器就弹出“ 找到多个与名为“Home”的控制器匹配的类型。如果为此请求(“control

网页插入SWF视频,如何带有播放控制按钮、进度条等!

将 Cache-Control: max-age 与 ETag 一起使用时会发生啥?

如何在 Rails 环境中使用 Cache-Control: max-age Header 来控制 Varnish 和浏览器?

浏览器缓存策略与 webpack 持久化缓存