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.
Related
I'm working on a VScode extension for my school open source project.
I was wondering there was a way to detect text input to the activeTextEditor window?
For example if someone were to paste a string in, could I grab detect that string similar to an OnInput in JavaScript? A setup would be spell checking or doing a replacement for commands, similar to Visual Studios' intellisense you type prop +tab +tab it auto generates code.
Let me know if you've heard of something that might work. Thanks
The api you are looking for is vscode.workspace.onDidChangeTextDocument. This event is fired whenever a document that VS Code knows about changes. It is fired with a TextDocumentChangeEvent object which includes all the text changes:
import * as vscode from 'vscode'
export function activate() {
vscode.workspace.onDidChangeTextDocument(changeEvent => {
console.log(`Did change: ${changeEvent.document.uri}`);
for (const change of changeEvent.contentChanges) {
console.log(change.range); // range of text being replaced
console.log(change.text); // text replacement
}
});
}
If you only care about changes to the active editor's text, just check to see if changeEvent.document matches the active editor's document.
I am completely new with javascript and html and have never written code in javascript before. I want to create a button that allows the user to copy the selected text in the textarea to the clipboard. I do not have a problem with using flash but I have never done it before so any help will much appreciated. Thanks!
for IE you can use
function copyData (str) {
window.clipboardData.setData('Text',str); }
or try the following link
http://www.phpgang.com/how-to-copy-text-to-clipboard-using-jquery_501.html
is there a way to strip specific tags from coming into tiny MCE through a copy+paste from an external source (e.g. Word)? I'd like to prevent font-family and image tags from being copy+pasted over, but have no problem with font-size etc.
Thank you!
You can't really stop someone from pasting something, so I believe your best bet would be to filter out the unwanted tags by calling a function on form submit, or onchange of the tiny MCE textarea. Then you could use some regular expression replacement to get rid of the unwanted tags.
EDIT: Actually there is a simple way. check the TinyMCE documentation.
Here is the link to a similar SO question with a detailed description of howto strip out unwanted tags: TinyMCE Paste As Plain Text
I don't know how useful this will be, but you might want to take a look at this jQuery plugin which allows you to filter tags and attributed from the text your are pasting.
FilteredPaste.js - A jQuery Plugin To Filter & Clean Pasted Input
Although "You can't really stop someone from pasting something" indeed, you can transform what your web app inserts into your TinyMCE textbox (or any other input).
Listen to the browser's native paste event.
Parse the clipboard's text/html string with DOMParser.
Make changes in the generated DOM tree.
Set the textbox content to the stripped content.
Prevent the paste default action.
Check this out:
editor.on ('paste', event => {
// Get clipboard's original HTML string
const clipboard = event.clipboardData
const originalHtml = clipboard.getData ('text/html')
// Parse HTML string into a DOMElement
const parser = new DOMParser
const doc = parser.parseFromString (originalHtml, 'text/html')
// Modify DOM tree
const elems = doc.body.querySelectorAll ('*')
elems.forEach (elem => {
elem.style.fontFamily = ''
// Do other modifications here...
})
// Set textbox content to modified HTML
editor.setContent (doc.body.innerHTML)
// Prevent pasting original content
event.preventDefault ()
})
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;
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.