Reputation: 437
So, currently I am working on a small button that asks the user to type the link for a video and then I am taking that link and making it into an iframe and inserting it into a contenteditable using document.execCommand("insertHTML", false, "<iframe width='350' height='551' src='<video_link_entered_by_user>'></iframe>")
. This works great and the video gets embedded into the contenteditable
.
The only problem is that if I do Command
+Z
or press undo
in Safari
, the iframe
won't get undone for some reason. It works in Firefox
, Chrome
, Edge
, and Opera
, but for some reason I think safari
doesn't understand how to undo
it.
Is there any workaround for this other than implementing my own undo/redo stack? I just want to be able to get rid of the iframe when the user chooses to undo
in safari as well and add it back when the user chooses to redo
. Please help and thanks in advance.
EDIT:
Here's a JS fiddle to demonstrate what I'm talking about. If you run this in any browser except Safari and press undo, it works. But not in Safari. http://jsfiddle.net/qg41pd3k/9/
Upvotes: 9
Views: 1016
Reputation: 740
I made a little cache solution to emulate the same behavior and make it works on Safari.
ctrl+Z
or cmd+Z
ctrl+Y
or cmd+Y
Hope this sample of code will help you.
Some optimisation can be added like debounce function, and increase the cache limit.
$(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>
Upvotes: 0
Reputation: 1420
I think it's not really supported in Safari. Checking at https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand, the execCommand method returns true/false whether the command is supported/enabled or not. In Safari it always returns false (according to my tests).
I think the only workaround is implementing you own undo/redo stack.
Upvotes: 2