I have seen a few sites now where if you highlight text of an article, copy it, and then paste in they can add more text to it.
Try copying and pasting a section of text from an article at http://belfasttelegraph.co.uk/ and you'll see what I mean - they add a link to the original article in the pasted text.
How is this done? I'm assuming there is some javascript at work here
This is a good effect, you can see the scripting that is fired on copy using Firebug (in Firefox).
Start up Firebug and load the page, choose clear (because the page uses a lot of ajax there are very quickly 100 requests). Then choose the 'All' tab and try to copy. You will see a request for a 1x1 pixel image but if you press on the + button to look at the details, you will see in the 'params' tab that this GET request passes your requested text as the 'content' parameter, with some xpath information that will be used to manipulate the clipboard DOM:
start_node_xpath /HTML/BODY[#id='belfast']/DIV[#id='root']/DIV[#id='content']/DIV[#id='mainColumn']/DIV[#id='article']/DIV[5]/P[39]/text()
end_node_xpath /HTML/BODY[#id='belfast']/DIV[#id='root']/DIV[#id='content']/DIV[#id='mainColumn']/DIV[#id='article']/DIV[5]/P[41]/text()
As #Crimson pointed out there are methods to manipulate the clipboard, like zeroclipboard which use Flash and an image.
I reckon that is how the technique is done by using the image get request to change the clipboard.
You will notice that this happens only when you use the key combination [Ctrl+C] and not if you highlight text and chose copy from the right-click menu.
They are simply trapping the [Ctrl+C] keystroke.
Further, to add data to the clipboard, take a look at this post:
How do I copy to the clipboard in JavaScript?
I've noticed lately an influx of this "clipboard hijacking" on websites. thefutoncritic.com, cracked.com... If you use Adblock just go into the "manual entries" list and add *post-copypaste.js* to it. This should prevent the sites from adding their ads to your clipboard.
An other solution used by other websites is to use jQuery and the 'copy' / 'cut' event :
$('body').bind('copy cut',function(e){manipulate();});
Some examples here :
http://www.mkyong.com/jquery/how-to-detect-copy-paste-and-cut-behavior-with-jquery/
A news site i visit use this function to append a "source" to the copied selection:
function addLink() {
var body_element = document.getElementsByTagName('body')[0];
var selection;
selection = window.getSelection();
// change this if you want
var pagelink = "<br><br>Fuente: Emol.com - <a href='"+document.location.href+"'>"+document.location.href+"</a><br>";
var copytext = selection + pagelink;
var newdiv = document.createElement('div');
newdiv.style.position='absolute';
newdiv.style.left='-99999px';
body_element.appendChild(newdiv);
newdiv.innerHTML = copytext;
selection.selectAllChildren(newdiv);
window.setTimeout(function() {
body_element.removeChild(newdiv);
},0);
}
document.oncopy = addLink;
Related
Right now i get the selected text with window.getSelection().toString(). But unfortunately this doesn't work for text in iFrames. It's for a chrome extension, so i don't need to hear about how iFrames suck ;).
If you have a reference to the iframe in question then
iframeEl.contentWindow.getSelection().toString();
... will do the job. If you want to get the selected text from all iframes, you could use window.frames, which is a collection of Window objects rather than frame/iframe elements:
var selectedTexts = [];
Array.prototype.forEach.call(window.frames, function(frameWin) {
selectedTexts.push( frameWin.getSelection().toString() );
});
I've turned a simple text box into one with editing features using the wysihtml5 editor. The project necessitates that the text box inject its html into an iframe. Previous to installing the editor, things were working great. Now, the jQuery for the iframe injection no longer works, since the editor has converted the textarea to an iframe. Any ideas on how I might convert the following jQuery to work with the editor?
(function() {
var frame = $('iframe#preview'),
contents = frame.contents(),
body = contents.find('body'),
styleTag = contents
.find('head')
.append('<style>*{font-family:arial}h2{color:#CC6600}</style>')
.children('style');
$('textarea').focus(function() {
var $this = $(this);
$this.keyup(function() {
body.html( $this.val() );
});
});
})();
I know that something needs to change in the $('textarea').focus call, I just don't know what. I'm new to the javascript/jQuery world and have tried a few possibilities, but so far haven't been able to figure this one out.
Many thanks for any insight.
As i know (probably i know what im talking), you cannot apply css styling to iframes outside of iframe (from parent document). You should TRY to embed styling inside iframe. Its because browser styling works with document, but iframe its another document and must ship with own css styling. Hope this helps
I would like to make a Chrome extension that lets users send emails with certain text automatically filled in. I was using a mailto: link, but it cannot handle strings longer than 1024 characters, and it cannot create html links. Is there a way I can fill in additional text and maybe even HTML links, from within the email page (perhaps with local storage)?
Unfortunately there is no native chrome/javascript API to my knowledge. I did some searching and found an open source option that someone was working on but it was very skeleton. He was hoping others would jump on with him and flesh it out.
Sounds like you're trying this:
For creating the URL, you can use the &body= tag and url encode the message however there is a limit to the length. It sounds like you already figured out how to open a new tag using chrome so you've been able to create shorter emails using nothing but a modified URL string. I did something similar to that on my first chrome exension. It looked something like this.
function sendToUrl(){ chrome.tabs.query({active:true, windowId: chrome.windows.WINDOW_ID_CURRENT}, function(tab) {
//while this seems to generate the URL correctly, gmail limits how long the body text can be therefore this is not a viable solution
//Also there is no javascript API therefore there is no hope of sending an email.
//Need to loop through each tab and not just the first one
var currentTab = tab[0];
var tabInformation = RPATH.getTab(currentTab.id);
var mailUrl = "https://mail.google.com/mail/?view=cm&fs=1&tf=1&su=My%20Subject&to=";
// grab the email addresss from popup.html
mailUrl += document.getElementById("to").value + "&body=";
// get formBody from popup.html
var formBody = document.getElementById("body").value;
...
//I did some other stuff that isn't relevant here
...
//Concat final mailto url
mailUrl = mailUrl + formBody;
chrome.extension.sendMessage({mailUrl: mailUrl}, function(response){ console.log(response.farewell);});
});}
For longer email bodies
That only gets you half way though. The only alternative I could think of was to split up the tab open and filling out the email body. You could modify the email body after page load completes using append. That might look something like what I have below. Notice I'm selecting the iframe element, then finding the body tag inside of there, and finally appending some html just after the tag opens. Notice the email body is nothing more then html so div, tr, br, etc tags should all work in creating a well formatted email. In my previous example I pulled the text from the form as a string. You could instead use jquery to clone the html on your popup.html page and append the cloned html. For simplicity's sake, I only put text inside the append.
$("iframe#:1t4").find("body.editable").append('<p>My long email body</p>');
I suppose from there you could run a click event but you could also leave that to the user.
I am using CLEditor, http://premiumsoftware.net/cleditor/, for my text editor. There is a function for 'paste as text' that when the button is clicked a pop up window appears with a textarea to paste your content in and the styles are stripped out.
What I would like to do is take this same functionality, but anytime someone paste into the primary textarea this action is performed automatically. How would I trigger this?
I have created a JS Fiddle, http://jsfiddle.net/helpinspireme/naubS/, but was unable to paste all the JS in there so to link to the main JS file for CLEditor visit their site: http://premiumsoftware.net/cleditor/
Thank you for your help.
I am aware that I am not answering your actual question, but in case your real problem is the garbage generated by a user who tries pasting text from Microsoft Office (Word for example) I would recommend to consider an alternative solution.
The CLEditor itself can switch between an iFrame (rich text mode) and a textarea (source mode). The 'Paste as text' functionality makes use of a textarea which does not support rich text by ifself, so it will not allow garbage html in the first place.
However if the editor is in rich text mode, it is very difficult to prevent a user pasting from Word (he can use the regular paste button, press CTRL-V or even use the right-mouse button context menu, which are all different events and hard to intercept using javascript). So now the damage is already done; you have messy html inside your editor. So instead of trying to sanitize the garbage produced by Word I implemented the following check (javascript) upon saving the captured input:
if(clEditorValue && (clEditorValue.indexOf('<!--') !== -1 || clEditorValue.indexOf('mso-ansi-language') !== -1 ) ) {
alert('Unable to process text pasted from Word, please use "Paste as text" or modify your input');
return;
}
I hope this answer is useful for other people trying to achieve the same.
When pasting into cleditor, the editor picks up all the html from the source. I ended up editing jquery.cleditor.js and added a bind function to the $doc.click(hidePopups) function. I used setTimeouts to allow the text to populate the input and the updateTextArea function to complete.
.bind("paste", function() {
setTimeout(function() {
refreshButtons(editor);
updateTextArea(editor, true);
//remove any and all html from the paste action
setTimeout(function() {
//clean up the html with removeHtml function
$(editor.doc.body).html(removeHtml($(editor.doc.body).html()));
//change the input value with new clean string
$("#" + editor.$area[0].id).val($(editor.doc.body).html());
}, 100);
}, 100);
})
I use the removeHtml function below to remove all the HTML from the pasted content.
//remove html altogether
function removeHtml(str) {
var regex = /(<([^>]+)>)/ig;
var result = str.replace(regex, "");
return result;
}
This solution is now in production.
I am playing around with creating an HTML-textarea based plain text editor to edit my scripts (using e.g. Mozilla Prism + a localhost install/ webserver). It works fine so far, but when I want to insert something at the cursor position, it gets slow in Firefox when there is a lot of text in the textarea (Chrome works fine). E.g. with 133k filled in the textarea it takes around 1 sec to perform inserting 4 spaces.
I already have and use elm.selectionStart and elm.selectionEnd. Based on these I then copy the text, manipulate it, and set the value back into the textarea -- perhaps that is what's causing the bottleneck (I'm using the similar approach as answered on this site before). Ideally, I would probably like to have something like elm.selectedText = 'foobar' but can't find this...
It doesn't necessarily need to be crossbrowser...
Can someone help?
According to this article on codemirror, using designMode is faster than using a textarea, because you can edit parts of the content instead of editing the whole text in one go.
There's an API that replaces the selected text: textarea.setRangeText('text').
Here's a demo:
const textarea = document.querySelector('textarea');
textarea.addEventListener('click', () => {
textarea.setRangeText('WOW');
});
<textarea rows="10" cols="40">Click anywhere or select any text in here. It will be replaced by WOW</textarea>
There's also document.execCommand('insertText') with undo support but it's not cross-browser. Try insert-text-textarea for a cross-browser solution.