使用insertHTML的execCommand的iframe撤消/重做(内容可编辑)

时间:2018-08-13 22:57:19

标签: javascript html iframe safari contenteditable

因此,当前,我正在使用一个小按钮,要求用户键入视频的链接,然后将其链接到iframe中,然后使用document.execCommand("insertHTML", false, "<iframe width='350' height='551' src='<video_link_entered_by_user>'></iframe>")将其插入到contenteditable中。这样效果很好,视频被嵌入到contenteditable中。

唯一的问题是,如果我执行Command + Z或在undo中按Safari,则iframe不会由于某些原因被撤消。它适用于FirefoxChromeEdgeOpera,但是由于某些原因,我认为safari不了解如何undo它。

除了实现自己的撤消/重做堆栈之外,还有其他解决方法吗?我只希望能够在用户选择在野生动物园中使用undo时摆脱iframe,并在用户选择redo时将其添加回去。请帮助并提前致谢。

编辑:

这是一个JS小提琴,用以演示我在说什么。如果您在Safari以外的任何浏览器中运行此程序,然后按undo,则可以使用。但不是在Safari中。 http://jsfiddle.net/qg41pd3k/9/

2 个答案:

答案 0 :(得分:2)

我认为Safari并不真正支持它。 在https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand处检查,无论是否支持/启用命令,execCommand方法都会返回true / false。在Safari中,它总是返回false(根据我的测试)。

我认为唯一的解决方法是实现您自己的撤消/重做堆栈。

答案 1 :(得分:0)

我制作了一个小缓存解决方案来模拟相同的行为并使它在Safari上运行。

  • 添加视频按钮
  • 撤消/重做按钮
  • ctrl+Zcmd+Z
  • ctrl+Ycmd+Y

希望这段代码示例对您有所帮助。

可以添加一些优化功能,例如防抖动功能,并增加缓存限制。

$(document).ready(function () {
    var $document = $(document);
    var $editor = $('#editor');
    var $redo = $('#redo');
    var $undo = $('#undo');
    var $addVideo = $('#add-video');

    var CACHE_LIMIT = 1000;
    var cache = [];
    var position = 0;
    var zKeyCode = 90;
    var yKeyCode = 89;
    
    var editorKeydownEventHandler = function (event) {
        var ctrl = (event.ctrlKey || event.metaKey);

        if (ctrl && event.keyCode === zKeyCode) {
            event.preventDefault();
            event.stopPropagation();
            undo();
        }
        else if (ctrl && event.keyCode === yKeyCode) {
            event.preventDefault();
            event.stopPropagation();
            redo();
        }
    };

    var editorInputEventHandler = function (event) {
        if(cache.length >= CACHE_LIMIT) {
            cache = cache.slice(1);
        }

        cache.push($editor.html());
        position++;
    };

    var redoClickEventHandler = function (event) {
        redo();
    };


    var undoClickEventHandler = function (event) {
        undo();
    };

    var addVideoClickEventHandler = function (event) {
        addVideo();
    };

    var redo = () => {
        if(cache[position + 1]) {
            position++;
            $editor.html(cache[position]);
        }
    };

    var undo = () => {
        console.log('undo');
        if(cache[position - 1]) {
            position--;
            $editor.html(cache[position]);
        }
    };

    var addVideo = function () {
        document.execCommand("insertHTML", false, "<iframe src='https://www.youtube.com/embed/9P6rdqiybaw' height='100' width='100'></iframe>")
    };

    $document.bind('keydown', editorKeydownEventHandler);
    $editor.bind('input', editorInputEventHandler);
    $redo.click(redoClickEventHandler);
    $undo.click(undoClickEventHandler);
    $addVideo.click(addVideoClickEventHandler);
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
     <div id="editor" contenteditable="true">
         Lorem ipsum dolor sit amet, consectetur adipisicing elit. At culpa exercitationem itaque maxime porro reiciendis repudiandae veniam vero! Alias at doloremque exercitationem fugiat ipsum natus nihil numquam provident sint, voluptatibus.
     </div>
     <button id="add-video">add video</button>
     <button id="undo">undo</button>
     <button id="redo">redo</button>
     <script
             src="https://code.jquery.com/jquery-3.3.1.min.js"
             crossorigin="anonymous"></script>
     <script src="index.js"></script>
</body>
</html>