Execcommand() Is Now Obsolete, What's the Alternative

Copy text to clipboard now that execCommand(copy) is obsolete

From Klaycon's comment to the question. The replacement is the Clipboard API. It is not implemented in all browsers, but most.

https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API

// In this example, the text to copy would be in an element with id = textcopy

var text_to_copy = document.getElementById("textcopy").innerHTML;

if (!navigator.clipboard){
// use old commandExec() way
} else{
navigator.clipboard.writeText(text_to_copy).then(
function(){
alert("yeah!"); // success
})
.catch(
function() {
alert("err"); // error
});
}

For some browsers (like Firefox) this only works when initiated by a user action. So, put the code inside a button listener, for example.

I tested this (Feb 2020) in (Windows) Chrome, Firefox, new Edge, Opera, iOS Safari, iOS Chrome, iOS app webview. Clipboard writeText works great.

Is there a replacement for document.execCommand? (or is it safe to use document.execCommand?)

Both the change to MDN marking document.execCommand() as obsolete and a related change at https://github.com/mdn/browser-compat-data/commit/2d3890a were made in part to due to https://w3c.github.io/editing/ActiveDocuments/execCommand.html having a big red warning with the following statements:

This spec is incomplete and it is not expected that it will advance beyond draft status. Authors should not use most of these features directly, but instead use JavaScript editing libraries. The features described in this document are not implemented consistently or fully by user agents, and it is not expected that this will change in the foreseeable future.

As far as any replacement method in vanilla JavaScript, the same warning box says it’s:

predicted that in the future both specs will be replaced by Content Editable and Input Events

…but sadly, we’re not there yet. So the unfortunate current state of things is, even though we have no replacement yet, we know document.execCommand() as-is now doesn’t work cross-browser interoperably — and browser projects aren’t gonna be fixing it. That’s why the MDN warning says:

its use is discouraged… Try to avoid using it.

So, as a comment above says, it’s similar to the case of drag-and-drop: It’s known to be broken in a number of ways, and it’s been that way for a long time because fixing it is basically not practical.

And that’s why the red warning box in the spec also says that developers and authors:

should not use most of these features directly, but instead use JavaScript editing libraries

The available JavaScript editing libraries in online rich-text editor tools such as CKEditor and TinyMCE “paper over” all the underlying brokenness in document.execCommand() for you. If you were to try to write your own robust handling for document.execCommand() in vanilla JavaScript from scratch, you’d basically — after a lot of work and time — end up having repeated the work that was done to create the JavaScript libraries underlying those tools.

So the bottom line is: to save yourself a lot of time and work, use one of the available libraries.

Beginner - Why is execCommand() obsolete?

Based on the MDN entry for Document.execCommand, in most cases the APIs made available by execCommand can be achieved using other modern, purpose-built JavaScript APIs that behave the same way across browsers.

Each command in execCommand's toolbox was contentiously implemented in different ways across browsers meaning that testing on every single browser was a necessity of web development. Just skimming through the draft spec you linked in the comments shows all of the notes detailing some of the different ways they were implemented. Because of these differences there was a shift away from HTML-based rich-text document rendering to canvas-based rendering for Google Docs and img-based rendering for Office 365 Web Apps (at least for viewing them, editing is still HTML-based).

Additionally, the MDN entry notes:

Return value

A boolean value that is false if the command is unsupported or disabled.

Note: document.execCommand() only returns true if it is invoked as part of a user interaction. You can't use it to verify browser support before calling a command. From Firefox 82, nested document.execCommand() calls will always return false.

Because execCommand can only be invoked as part of user interaction, it might work in one bit of your code, and not in another - which can cause time-consuming headaches that involve learning the intricacies of JavaScript's event loop.

Importantly, with the advent of JavaScript running on mobile devices and modern JavaScript frameworks having their own "event->queue->render" loops, what even defines a user interaction event? A click, tap, keypress, etc? What about a screen rotation or resizing the window? What about asynchronous event changes where you make a server request and then show the user something based on the result? How would the engine know those two things are linked together with modern Promise-based APIs rather than callback-based APIs?

If you want to do some further digging, take a look at this thread on another question asking about what replacements are available to execCommand().

My jquery execCommand isn't working as i want

(It's worth pointing out that execCommand is obsolete, and should not be used. See the answers to this question for more current alternatives.)

execCommand acts on the "current editable region". Clicking on the li takes focus away from the editable region, so by the time your code runs there isn't a current editable region to act on.

You can work around this by triggering the action on mousedown instead of on click, so it fires before the browser focus changes:

$('li[data-role]').mousedown(function() {
document.execCommand($(this).data("role"), false);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li data-role="bold" class="bold_str">Bold</li>
<li data-role="strikeThrough" class="strike_str">Strikethrough</li>
<li data-role="underline" class="underline_str">Underline</li>
<li data-role="undo" class="undo_str">Undo</li>
<li data-role="redo" class="redo_str">Redo</li>

<div class="output_wp">
<div class="output" id="output" contenteditable>lorem ipsum lorem ipsum</div>
</div>


Related Topics



Leave a reply



Submit