Dealing with Clipboard Data

I have the following code where I’m copying and then pasting some stuff like the following in the text area. I have it setup this way because when I paste the following three lines, the cursor stays right after the last line HIJ123 and not below HIJ123.

ABC123
DEF123
HIJ123

I want to achieve the following while copying and pasting.

1.After pasting the above three lines in the text area, if I want to paste the same thing (ideally it’s going to be different lines of text similar to above)again in the text area, let’s say after pressing enter after ABC123, the next three lines get pasted after HIJ123 as shown in the image below,even though the cursor was after ABC123 after pressing enter after ABC123. Is it possible to get it pasted where I am looking for - after ABC123 in above scenario?

2.Is there a way I could clear the clipboard data after pasting the contents? I was trying to achieve something using the Clear Data! button, but it doesn’t seem to work and throws Uncaught TypeError: element.value.clearData is not a function when I click on Clear Data button.

Here is my JsFiddle demonstrating the same.

I’m using both Chrome and Firefox browsers if that matters.

Didn’t we cover #1 in the last iteration of this thread, Jack? I could have sworn we did…

clearData is a function of the Event.clipboardData object. In your code, the Event would whatever parameter you put into the event listener (currently you have no parameter specified; compare and contrast line 3, where you specify e as that parameter).

basically, addEventListener((e) => e.clipboardData.DoStuff

Yup, found our old thread.

I am gonna give it a try and ask questions here, as that one is closed.

1 Like

On this part, were you recommending like this?

document.getElementById('clear-button').addEventListener('click', (e) =>  {
    console.log("What is element here?");
    console.log(element);
    e.clipboardData.clearData();


    });

This still gives me an error Uncaught TypeError: Cannot read properties of undefined (reading 'clearData')"

Oh, apologies, I should have read the MDN a little clearer.
clipboardData only exists for Events of the Clipboard type (paste, copy, cut), and it wouldnt… effect the user’s clipboard directly? (because that would make sense, Marc. Security is a thing.)

What you could do instead is write to the user’s clipboard a blank string, which would effectively ‘empty’ the clipboard without trying to modify the clipboard history.

navigator.clipboard.writeText("");

No problem.

Could you check if this is how it should be written then? This doesn’t seem to clearing the textarea. It didn’t throw any error as well. I’m testing it on Chrome browser.

 document.getElementById('clear-button').addEventListener('click', function () {
    console.log("What is element here?");
    console.log(element);
     navigator.clipboard.writeText("");


    });

Are you trying to clear the textarea, or the clipboard?
You dont have any code in that block that would erase the textarea.

Both. Such that user could copy new one and paste it.

element.value = "";
(add, dont replace, obviously)

Thanks. This worked:

document.getElementById('clear-button').addEventListener('click', function () {
    console.log("What is element here?");
    console.log(element);
     navigator.clipboard.writeText("");
     element.value = "";


    });

Now looking into the first part.

One issue I’m facing after clearing clipboard data and text area is as follows:

Firstly, to explain more, I have a button Add Controls which when clicked, an addControls function is called which pops up a jQuery dialog and I have a Clear Controls button which when pressed, clears out the pasted data in the text area as well as the clipboard data. However, I’m noticing that after hitting the Clear Controls button, if I let the dialog open, copy another thing from an excel sheet to paste on the text area, it is getting pasted two times, which is something I’m not understanding.
Here’s the image of how it looks in a jQuery dialog with two contents pasted next to each other.

Any idea what am I doing wrong here? Should I consider closing the dialog everytime Clear Controls button is clicked?

function addControls() {
  
  let element = document.getElementById("controlName");
  element.addEventListener("paste", (e) => {
    e.preventDefault();
    element.value += (event.clipboardData || window.clipboardData)
      .getData("text")
      .trim();
  });

  //control-dialog
  $("#control-dialog").dialog({
    modal: true,
    width: 400,
    buttons: {
      Add: function () {
	     //do something
	  },
	    "Clear Controls": function () {
        //write a blank string to the user's clipboard, which would effectively 'empty'
        // the clipboard without trying to modify the clipboard history
        navigator.clipboard.writeText("");
        //clear the text area
        element.value = "";
      },
      Cancel: function () {
        $(this).dialog("close");
      },
	   },
  });

I think this won’t help as I tried closing the dialog using Cancel button and then, opened the dialog again, hit Clear Controls button. Copied the data again PRS123 and it got pasted thrice which is weird.

Is something calling addControls more than once? If you bind the paste event multiple times to the same text field, it would account for this behavior.

addEventListener ADDS a listener to an element, it doesnt overwrite existing listeners.

After Add button of the dialog is used, the dialog closes, and addControls can be used again if user want to repeat same operation with different copied clipboard data. Did you mean to say the same thing when you say Is something calling addControls more than once? or were you referring if addControls is called more than once at the same time?

No, just more than once. You’re binding this code:

every time addControls() is called.

This code (the bit inside the {}'s), basically, is a piece of paper that says “Paste what’s on the clipboard.”
Every time your code runs addEventListener, it prints off a copy of the paper, and sticks it on a bulletin board.

When the user hits ctrl-V, a paste event is begun. Javascript looks at its bulletin board, and executes whatever is written on each bit of paper.

If there are 2 copies of the paper that say “Paste what’s on the clipboard”, Javascript reads the first one, pastes what’s on the clipboard into the element, then reads the second bit of paper, and pastes what’s on the clipboard into the element. It did exactly what you instructed it to do.

If you run addControls again, you print another bit of paper, and tack it to the bulletin board.

The idea would be to only print 1 copy of the paper. (And to the code geeks that follow, yes, i know that you could rip the paper off the bulletin board (removeEventListener) or burn the bulletin board down (destroy and recreate the element), but the simplest answer is to only bind 1 event.)

Thanks for explaining in detail. Yes, there is a possibility that the user will be opening the dialog multiple times as needed, which will cause addControls() to run multiple times.

Question -
If I clear the clipboard data and text area as we discussed above, everytime the dialog closes, then it shouldn’t be a problem, right? It seems like it is happening despite clearing the clipboard data and text area.

Since addControls is going to be used multiple times, is it possible to only bind one event?

I can see the logic, but no, it’s not the contents of the clipboard that are the problem, it’s that whatever is in the clipboard is acted on multiple times.

Closing the dialog, in most cases (and from the descriptions you’ve given here, i’m pretty sure in your case too) doesnt destroy the textbox (which is the “burning the bulletin board down” option i mentioned before), it just hides it, so that it can use it again later. The bulletin board in my allegory is your textbox. If opening the modal created the textbox (and bound the paste event), and closing it destroyed it, you wouldnt have the problem.

The simplest solution is to move the binding of the event listener outside your function, so that it gets bound exactly once. Then your modal can hide and show the same text box as many times as it wants to, and there’s only one event listener waiting when someone pastes something.

I moved the following part outside my addControls function and put it inside the script tag of the main page:

let element = document.getElementById("post-text");

    element.addEventListener('paste',(e) => { 
      e.preventDefault();
      console.log(event.clipboardData);
      element.value += (event.clipboardData || window.clipboardData).getData("text").trim()
    } );

Still, it seems to be creating same problem :frowning:

https://jsfiddle.net/walker123/u83gfkbz/18 seems to be working for me, other than we’re back to pasting in the end rather than the middle… have you got a different fiddle i should be looking at?

Maybe I should create a fiddle with jQuery dialog with addControls() function to see if I am able to replicate the issue. The one you shared is the basic one without the addControls() function related issue I am referring to starting from this post