Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept a style parameter to specify the copied style. #80

Closed
wants to merge 1 commit into from

Conversation

julienw
Copy link
Collaborator

@julienw julienw commented May 4, 2019

If style parameter isn't specified, this forces a text/plain copy to make it easier to work with word processors.
This also changes the example code to exhibit the bug of issue #46 so
that it's easier to test.

Fixes #46

@julienw julienw force-pushed the fix-paste-in-gdocs branch 2 times, most recently from 2986187 to 593bd83 Compare May 4, 2019 13:16
If `style` parameter isn't specified, this forces a text/plain copy to make it easier to work with word processors.
This also changes the example code to exhibit the bug of issue sudodoki#46 so
that it's easier to test.

Fixes sudodoki#46
Copy link
Collaborator Author

@julienw julienw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this code with both Chrome and Firefox using the example page, and this seems to work for me.
I tried pasting to a google drive document with white background, and also with a table with red background to check that both the black-on-white and no-formatting cases were working fine too.

I couldn't try in IE, Edge or Safari, so it would be a good idea to try there too.

Sorry for coming up with this solution a bit late, this was in my head for some time and just slipped out of my attention :/ I hope you'll like it...

@@ -23,7 +26,7 @@ <h2 id="multiline-text">Multiline text copy</h2>
some multiline text
for us to copy</textarea>
<div class="half">
<button data-test="init-multiline-text">Click to copy multiline text</button>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that data-test wasn't used at all so I repurposed this to make it easier to target buttons to add the click event listeners.

interface Options {
debug?: boolean;
message?: string;
format?: string; // MIME type
style?: boolean | StyleOption; // MIME type
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about typescript, I didn't check this is working as expected, so please double check!

@@ -65,7 +80,7 @@ function copy(text, options) {
debug && console.error("unable to copy using execCommand: ", err);
debug && console.warn("trying IE specific stuff");
try {
window.clipboardData.setData(options.format || "text", text);
window.clipboardData.setData("text", text);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the documentation on microsoft website and there's no possibility to pass rich text. So I reverted to the previous code here.

@@ -1 +1 @@
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).copyToClipboard=e()}}(function(){return function c(a,i,s){function l(t,e){if(!i[t]){if(!a[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=i[t]={exports:{}};a[t][0].call(r.exports,function(e){return l(a[t][1][e]||e)},r,r.exports,c,a,i,s)}return i[t].exports}for(var u="function"==typeof require&&require,e=0;e<s.length;e++)l(s[e]);return l}({1:[function(e,t,n){"use strict";var l=e("toggle-selection");t.exports=function(t,n){var o,r,e,c,a,i,s=!1;n||(n={}),o=n.debug||!1;try{if(e=l(),c=document.createRange(),a=document.getSelection(),(i=document.createElement("span")).textContent=t,i.style.all="unset",i.style.position="fixed",i.style.top=0,i.style.clip="rect(0, 0, 0, 0)",i.style.whiteSpace="pre",i.style.webkitUserSelect="text",i.style.MozUserSelect="text",i.style.msUserSelect="text",i.style.userSelect="text",i.addEventListener("copy",function(e){e.stopPropagation()}),document.body.appendChild(i),c.selectNodeContents(i),a.addRange(c),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");s=!0}catch(e){o&&console.error("unable to copy using execCommand: ",e),o&&console.warn("trying IE specific stuff");try{window.clipboardData.setData("text",t),s=!0}catch(e){o&&console.error("unable to copy using clipboardData: ",e),o&&console.error("falling back to prompt"),r=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in n?n.message:"Copy to clipboard: #{key}, Enter"),window.prompt(r,t)}}finally{a&&("function"==typeof a.removeRange?a.removeRange(c):a.removeAllRanges()),i&&document.body.removeChild(i),e()}return s}},{"toggle-selection":2}],2:[function(e,t,n){t.exports=function(){var t=document.getSelection();if(!t.rangeCount)return function(){};for(var e=document.activeElement,n=[],o=0;o<t.rangeCount;o++)n.push(t.getRangeAt(o));switch(e.tagName.toUpperCase()){case"INPUT":case"TEXTAREA":e.blur();break;default:e=null}return t.removeAllRanges(),function(){"Caret"===t.type&&t.removeAllRanges(),t.rangeCount||n.forEach(function(e){t.addRange(e)}),e&&e.focus()}}},{}]},{},[1])(1)});
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).copyToClipboard=e()}}(function(){return function a(c,l,i){function s(t,e){if(!l[t]){if(!c[t]){var o="function"==typeof require&&require;if(!e&&o)return o(t,!0);if(u)return u(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var r=l[t]={exports:{}};c[t][0].call(r.exports,function(e){return s(c[t][1][e]||e)},r,r.exports,a,c,l,i)}return l[t].exports}for(var u="function"==typeof require&&require,e=0;e<i.length;e++)s(i[e]);return s}({1:[function(e,t,o){"use strict";var u=e("toggle-selection");t.exports=function(t,o){var n,r,e,a,c,l,i,s=!1;o||(o={}),o.style&&(i=Object.assign({background:"white",text:"black"},o.style)),n=o.debug||!1;try{if(e=u(),a=document.createRange(),c=document.getSelection(),(l=document.createElement("span")).textContent=t,l.style.all="unset",i&&(l.style.backgroundColor=i.background,l.style.color=i.text),l.style.position="fixed",l.style.top=0,l.style.clip="rect(0, 0, 0, 0)",l.style.whiteSpace="pre",l.style.webkitUserSelect="text",l.style.MozUserSelect="text",l.style.msUserSelect="text",l.style.userSelect="text",l.addEventListener("copy",function(e){e.stopPropagation(),i||(e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData("text/plain",t))}),document.body.appendChild(l),a.selectNodeContents(l),c.addRange(a),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");s=!0}catch(e){n&&console.error("unable to copy using execCommand: ",e),n&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(o.format||"text",t),s=!0}catch(e){n&&console.error("unable to copy using clipboardData: ",e),n&&console.error("falling back to prompt"),r=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in o?o.message:"Copy to clipboard: #{key}, Enter"),window.prompt(r,t)}}finally{c&&("function"==typeof c.removeRange?c.removeRange(a):c.removeAllRanges()),l&&document.body.removeChild(l),e()}return s}},{"toggle-selection":2}],2:[function(e,t,o){t.exports=function(){var t=document.getSelection();if(!t.rangeCount)return function(){};for(var e=document.activeElement,o=[],n=0;n<t.rangeCount;n++)o.push(t.getRangeAt(n));switch(e.tagName.toUpperCase()){case"INPUT":case"TEXTAREA":e.blur();break;default:e=null}return t.removeAllRanges(),function(){"Caret"===t.type&&t.removeAllRanges(),t.rangeCount||o.forEach(function(e){t.addRange(e)}),e&&e.focus()}}},{}]},{},[1])(1)});
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the result from running yarn pretest, so that I could test using the example code.

@julienw
Copy link
Collaborator Author

julienw commented May 4, 2019

Also, as a quick note, I don't like the previous solution using a format property because I think it's not versatile enough. I don't think that copying text using whatever color the <body> has is what users would want...

@julienw
Copy link
Collaborator Author

julienw commented May 18, 2019

ping @sudodoki, hey, do you think you'll be albe to look at this PR soon?
I believe the previous solution 1/ doesn't provide much value, and 2/ doesn't fix the background issue in Chrome. And that this solution brings a much better value. Tell me what you think!

@sudodoki
Copy link
Owner

@julienw if this change is accepted what should user do if they don't want any style changes, yet want a rich text copied?

@sudodoki
Copy link
Owner

TBH, I think I'm slightly reluctant to merge this as this is a breaking change and 1) I'm still not 100% sold this is a right way to fix this, 2) currently I don't have too much time on my hands to deal with this. 🤷‍♂ Although your enthusiasm about this is inspiring.

@julienw
Copy link
Collaborator Author

julienw commented May 19, 2019

The current situation is less than ideal because:

  1. it's kind of broken in chrome if there's a background color on the body (that's issue Copied text has a grey background when pasted into gmail or google docs. #46)
  2. specifying a format is broken in old IE (but maybe we don't mind much)
  3. it's possible to copy a rich text, but we don't control the style, and the behavior is different depending on the browser, so what's the point? I admit I really don't get it :-)

This 3rd point also answers your question if this change is accepted what should user do if they don't want any style changes, yet want a rich text copied?. I don't understand the use case.
I think this would work OK cross-browser only on a webpage that doesn't have its background set. As soon as the page has a background set the behavior will be different in Chrome vs Firefox (and probably others that I haven't tried). I personally think it's not a good thing.

That's why in this PR I added some code to force a white background and a black text color, so that we have some cross-browser consistency.

I guess I could try to keep the code using format so that it's not a breaking change anymore, and mark it clearly as "obsolete" so that we could remove it later. I can do that if you want to.

@julienw julienw closed this Jan 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Copied text has a grey background when pasted into gmail or google docs.
2 participants