Home > Enterprise >  Changing only the name of a variable appears to break JavaScript code to copy a link to the clipboar
Changing only the name of a variable appears to break JavaScript code to copy a link to the clipboar

Time:09-06

I have written a short JavaScript function to write a link to the clipboard so that it will still appear as a clickable link when pasted into programs that support rich text such as Microsoft Word, based on the answer here.

content.js

function copyLink() {
  /**
  * Write a link to the clipboard
  */
  var text = "Google"
  var url = "https://www.google.com"
  var type = "text/html";  
  var blob = new Blob([`<a href=${url}>${text}</a>`], { type });
  
  myClipboardItem = new ClipboardItem({ [type]: blob })
  var data = [myClipboardItem];
  navigator.clipboard.write(data).then(
    function () {
      console.log("Link written to clipboard")
    },
    function () {
      console.log("Failed to write to clipboard")
    }
  );
}

I'm testing using the following HTML page:

index.html

<html>
    <head>
        <script src="content.js"></script>
    </head>
    <body>
        <button onclick="copyLink()">Copy</button>
    </body>
</html>

The above code works perfectly - when I open index.html in Google Chrome and click the Copy button, the console displays "Link written to clipboard", and when I paste into Microsoft Word I get the formatted link as expected.

I would now like to modify the function to copy multiple types, and as part of the code change I would like to change the variable name type to typeHtml. Changing the name of a variable consistently across a function should not alter the behaviour or result, right? type appears 3 times in the function: once when it is first assigned, and once each inside new Blob and new ClipboardItem. So I change my code to the following:

content.js (after variable name change)

function copyLink() {
  /**
  * Write a link to the clipboard
  */
  var text = "Google"
  var url = "https://www.google.com"
  var typeHtml = "text/html";  
  var blob = new Blob([`<a href=${url}>${text}</a>`], { typeHtml });
  
  myClipboardItem = new ClipboardItem({ [typeHtml]: blob })
  var data = [myClipboardItem];
  navigator.clipboard.write(data).then(
    function () {
      console.log("Link written to clipboard")
    },
    function () {
      console.log("Failed to write to clipboard")
    }
  );
}

No changes have been made to the code except for the variable name change. However, when I refresh index.html and hit the button again, the console shows "Failed to write to clipboard" and nothing is copied to the clipboard. This occurs no matter how many times I refresh the page or hit the button, but the code works perfectly again when I revert to the original version with the variable named type. I've also tried other variable names such as t, but these also break the code and it only works when the variable is named type.

What am I missing? Any help would be much appreciated.

CodePudding user response:

In your original code, doing

var blob = new Blob([`<a href=${url}>${text}</a>`], { type });

constructs an object that looks like the following:

var blob = new Blob([`<a href=${url}>${text}</a>`], { type: "text/html" });

Which works because the constructor accepts a type property in the options object.

But if you do

var blob = new Blob([`<a href=${url}>${text}</a>`], { typeHtml });

then the object you pass is

var blob = new Blob([`<a href=${url}>${text}</a>`], { typeHtml: "text/html" });

typeHtml is not something that the Blob constructor understands, so it's ignored, and the blob doesn't get created properly.

If you want to rename the variable, you can't use shorthand syntax for the object initializer.

var blob = new Blob([`<a href=${url}>${text}</a>`], { type: typeHtml });

CodePudding user response:

Fixed after Jaromanda X commented that { typeHtml } is short for { typeHtml: typeHtml }. The name of the Blob constructor property is type, so it should be { type: typeHtml }

Working code:

function copyLink() {
  /**
   * Write a link to the clipboard
   */
  var text = "Google"
  var url = "https://www.google.com"
  var typeHtml = "text/html";  
  var blob = new Blob([`<a href=${url}>${text}</a>`], { type: typeHtml });

  myClipboardItem = new ClipboardItem({ [typeHtml]: blob })
  var data = [myClipboardItem];
  navigator.clipboard.write(data).then(
    function () {
      console.log("Link written to clipboard")
    },
    function () {
      console.log("Failed to write to clipboard")
    }
  );
}
  • Related