How to stop Chrome from turning relative links to absolute links on copy/paste?
TL;DR - The one that in charge for the pasted content is the program that puts it in the clipboard.
Every time that you copy something into the clipboard, the application that does the copy can put there several data-types, so the program that you paste
into will be able to use the one that works best for it. In case of a browser - when you select a content of a webpage and copy to your clipboard - the browser will create two types (html/plain
and text/html
), so if you paste that content into a program that can handle html - the data you will paste will be html, but if not - that data will be plain text.
Basically you have two options:
- Override the content that the browser saves in the clipboard (this way - no matter where the content will be pasted - it will look exactly the way you want to)
- Hijack the paste event, get the data from the clipboard, change it the way you want, and put it into the editor yourself.
$('#text').on('paste', function(e) { if ($('input[name=paste-type]:checked').val() == 'special') { e.preventDefault(); if (window.getSelection) { sel = window.getSelection(); if (sel.rangeCount) { range = sel.getRangeAt(0); range.deleteContents(); node = document.createElement("p"); text = 'Replacement text only for the paste' node.appendChild(document.createTextNode(text)) range.insertNode(node); } } }});$(document).on('copy', function(e) { if ($('input[name=copy-type]:checked').val() == 'special') { e.preventDefault(); if (window.getSelection) { sel = window.getSelection(); if (sel.rangeCount) { range = sel.getRangeAt(0); nodes = range.cloneContents().childNodes content = '' contentPlain = '' for (var i = 0; i < nodes.length; i++) { node = nodes[i]; contentPlain += node.textContent if (node.nodeType == 3) { content += node.textContent } else if (node.nodeType == 1) { content += node.outerHTML } } } } else { content = '<span style="color: red; background: yellow;">Replacement text only for the copy</span>'; } e.originalEvent.clipboardData.setData('text/html', content); e.originalEvent.clipboardData.setData('text/plain', contentPlain); }});$('#btn1').click(function() { $('#ta1').val($('#text').html());});
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script><div id="text" contenteditable="true" style="width: 400px; height :250px; border: 1px solid black;">Paste your text here...</div><br /><textarea id="ta1" style="width: 400px; height: 150px; border: 1px solid green;" disabled="disabled"></textarea><br /><button id="btn1">View HTML</button><br /><label for="reg"><input type="radio" name="paste-type" value="regular" id="reg" checked="checked" /> Regular Paste</label><label for="special"><input type="radio" name="paste-type" value="special" id="special" /> Force my paste</label><br /><br /><label for="copy-reg"><input type="radio" name="copy-type" value="regular" id="copy-reg" checked="checked" /> Regular Copy</label><label for="copy-special"><input type="radio" name="copy-type" value="special" id="copy-special" /> Force my copy</label><br /><br /><div style="width: 400px; height: 300px; border: 1px solid red;"> <p>Nonumes molestiae <b>scripserit mei eu. In sea singulis evertitur</b>, verear inimicus delicatissimi ad eam. Eu eros scripserit cum, nam ferri ludus saperet te, ex sea nostro prompta inciderint. Est at causae .</p> <p>Quem feugait nam cu, sed <span style="background: red;">tantas meliore eu. Propriae efficiendi at</span> has, in usu nusquam noluisse, no nam natum verterem. Eu tation dignissim pro. Id eos wisi mollis commune</p> <p>Ea has quando blandit <a href="#a1">intellegebat, iusto</a> fabulas eos in, per consul suscipit inciderint cu. Ea veri possim nostrud vis. Id civibi. Ut duo posse <a href="#a2">graecis voluptatibus</a>, mea eu errem possim quaestio.</p></div>
In the example above I gave options you can play with (original copy/paste and special copy/paste).
You can see that in the example of special-copy - I built the html
string to put in the clipboard from the selection in the page (based on the DOM
elements). This way I was able to get the exact value of the href
(without changing it to the absolute path).
For your convenient, the exact same code in jsfiddle:https://jsfiddle.net/m0ad3uaa/
The issue is client-side. Browsers copy links with absolute URLs, this is to prevent issues arising when you paste links into different areas.
For example, if I click a link on http://site1.com
which looks like this <a href="/myresource.jpg">
, I'll be directed to http://site1.com/myresource.jpg
.
Now, if you were to copy that same tag to http://site2.com
, the link would now point to http://site2.com/myresource.jpg
, which may or may not exist.
This makes sense in most cases, as if you're using Chrome, you're unlikely to be trying to copy a site, assets and all. It also fixes issues where <img>
tags would point to assets which don't exist.
However, in saying all of that, it is possible to programmatically mess with what is being selected.
There's a great example of this here:http://bavotasan.com/2010/add-a-copyright-notice-to-copied-text/
Essentially, you'll just want to change document.oncopy
to take window.getSelection()
and remove all instances of your domain name, ensuring that the links are relative instead.