-1

I'm writing a script that takes text from a file and adds/edits a checksum at the end (using a text editor like notepad++ to go to/from hard drive).

The browser textarea translates both \n and \r\n to \n when you copy/paste into it, and then converts to either \n or \r\n when going to another program (depending on which operating system you are in). This makes the checksum incorrect (even if you ignore the mangling of any non-printable characters in the checksum itself).

I guess I might be able to bypass this with the open/save file dialog (as long as there are not any similar surprises here), but there are other projects this would also be useful for.

Hopeful Llama
  • 728
  • 5
  • 26
Dustin Soodak
  • 553
  • 5
  • 15
  • At what point is the checksum created? Would you have the opportunity to normalise all instances of `\n` to `\r\n` by intercepting the paste event in the browser? – AM Douglas Nov 01 '16 at 20:04
  • Is there a way to put your own version of the text into the clipboard with javascript? I thought it needed flash or special plugins to interact with the clipboard directly. – Dustin Soodak Nov 01 '16 at 20:16

2 Answers2

0

You could try using a <pre> element with the contenteditable="true" attribute instead of a textarea. This should theoretically preserve the input.


Edit I

You could intercept the onpaste event and normalise all instances of \r\n to \n and then generate the checksum. The JavaScript might look like this:

var input_el = document.querySelector('.your-textarea');

input_el.onpaste = function(e){
  typeof e !== 'undefined' && e.preventDefault();      

  var clipbd_data;
  
  // handle IE edge case
  if (window.clipboardData && window.clipboardData.getData) {
    clipbd_data = window.clipboardData.getData('Text').replace(/\r\n/g, "\n").replace(/^(.*)\n*$/gm, "$1");
  }
  else if (e.clipboardData && e.clipboardData.getData) {
    clipbd_data = e.clipboardData.getData('text/plain').replace(/\r\n/g, "\n").replace(/^(.*)\n*$/gm, "$1");
  }
  else {
    return; // functionality not supported
  }

  input_el.value = clipbd_data;

  return false;

};

Note: I have not tested this.

Source for regex


Edit II

Intercepting the copy event

First, add the following onclick handler to the textarea:

<textarea class="your-textarea" onfocus="this.select()" onclick="this.focus();this.select()">
</textarea>
<!-- could optionally add ontouchstart="this.select()" for phones, if you need to -->

This is important, because we're intercepting the copy event — it's not as though we can grab the exact data the user copied, because they haven't copied it yet, so we need to force the user to select all the text in the textarea automatically so we can pass the whole contents of the textarea to the clipboard (after normalisation). This should be what the user wants to do anyway, so it shouldn't present a usability problem...

Now, to intercept copy and add your own text:

var txt_area = document.querySelector('.your-textarea');

txt_area.addEventListener('copy', function(e){
  // stop the normal copy behaviour
  typeof e !== 'undefined' && e.preventDefault();
  
  // get the contents of the textarea
  var txt_before = txt_area.value;
  
  // normalise
  var txt_after = txt_before.replace(/\r\n/g, "\n").replace(/^(.*)\n*$/gm, "$1");

  e.clipboardData.setData('text/plain', txt_after);
});
Community
  • 1
  • 1
AM Douglas
  • 1,873
  • 1
  • 13
  • 17
  • I had no idea you could make
     editable! Unfortunately, it translates '\r' into '\n' when pasting into a text editor (ubuntu,firefox) even though it displayed '\r\n' as just one newline when pasted from the text editor to browser.
    – Dustin Soodak Nov 01 '16 at 18:04
  • I'd also prefer to have scrollbars though this is not absolutely necessary – Dustin Soodak Nov 01 '16 at 18:06
  • Bugger. Sorry to waste your time, I didn't have time to test the idea. I have another idea which I'll share in an hour or so when I have time. – AM Douglas Nov 01 '16 at 19:02
  • anything which results in leaning something new is not a waste of time :) – Dustin Soodak Nov 01 '16 at 20:19
  • @DustinSoodak okay, I have amended my answer. Might need to refresh your browser because StackOverflow leverages the browser cache a little too enthusiastically. – AM Douglas Nov 02 '16 at 01:07
  • Is there also a way to intercept text before it gets to clipboard via copy? If so, then this will solve my problem. – Dustin Soodak Nov 02 '16 at 18:57
  • I see what you mean...it wouldn't refresh until I gave up and tried posting my response again. – Dustin Soodak Nov 02 '16 at 19:25
  • @DustinSoodak okay, that code should be what you need to intercept copy and pass your normalised text to user's clipboard. – AM Douglas Nov 02 '16 at 19:58
  • I mean to say that the new code added in my second edit should work for the `copy` interception. If you need to support older browsers (IE8 or less) I believe you can add the event in the tranditional `oncopy=` way. – AM Douglas Nov 02 '16 at 20:10
  • Just found another problem: It "helpfully" removes \r even if you go directly from the clipboard to a javascript string so you can't even tell if the original file used \n or \r\n. This means that the checksum will be incorrectly pasted whenever it contains instances of \r. – Dustin Soodak Nov 02 '16 at 21:00
0

It looks like this may be impossible, so I am posting another question on using a different approach to getting data from javascript to a file without it being corrupted. See "Keep javascript blob from editing data when saving file"

Community
  • 1
  • 1
Dustin Soodak
  • 553
  • 5
  • 15