Here is the JSFiddle demo: http://jsfiddle.net/qox0yxb4/
I am using type() to create a typewriter affect (each character is printed on the screen with a delay in between). I use addTextToScreen(textForScreen) to add text to the queue which is then added to the screen through type(). When I call addTextToScreen() from within the JavaScript, the text seems to be formatted as it does NOT overflow on the x-axis, however when I accept input from an HTML <input> tag (printText()), the text overflows on the x-axis.
Here are the JavaScript methods:
var i = 0,
isTag=false,
text;
var typeTime = 45;
function type() {
if (text === textOnScreen){
setTimeout(function(){type();}, typeTime);
return;
}
text = textOnScreen.slice(0, i+1);
i++;
document.getElementById('paraText').innerHTML = text;
var char = text.slice(-1);
console.log(char);
if( char === '<' ) isTag = true;
if( char === '>' ) isTag = false;
if (isTag) return type();
setTimeout(function(){type();}, typeTime);
}
function addTextToScreen(textForScreen){
textOnScreen = textOnScreen + textForScreen;
}
type();
function printText(event) {
if(event.keyCode == 13){
printText = document.getElementById("inputText").value.toString();
addTextToScreen("<br>" + printText.toString());
x = document.getElementById("inputText");
x.value = "";
}
}
I also noticed that whenever I paste text into the input box (the text can be from anywhere) it seems to be formatted, and it does NOT overflow.
Add this css property to #paraText:
word-wrap:break-word;
JS Fiddle Demo
Josh suggested using break-all, here is the difference.
The magic CSS rule you're missing is word-break: break-all;. Add that, and it works just like you'd expect.
Proof
Related
I have a text area and I dynamically add data to it and it works fine. What I wanted to achieve was after the data is appended that data cant be altered (edited) but after the last element of the data user can start typing on the textarea. I was thinking of maybe calculating the length of string data the set read-only to that part. How can I achieve this? Any help is appreciated. Thanks in advance.
For a visual example take a look at the terminal of this website: https://www.online-python.com/
function test() {
x = 'this is a string to be appended to text area'
document.getElementById("textArea").value = x;
}
<textarea id="textArea"></textarea>
<button onclick="test()">Append</button>
You can add a keydown event listener that checks whether the selectionStart is smaller than the length of the textarea's value minus the length of the string appended:
let x = 'this is a string to be appended to text area'
var hasAppended = false;
function test() {
hasAppended = true
document.getElementById("textArea").value = x;
}
textArea.addEventListener('keydown', function(e) {
if (hasAppended) {
if (this.selectionStart > this.value.length - x.length && this.selectionStart != this.value.length) {
e.preventDefault()
e.stopPropagation()
}
}
})
<textarea id="textArea"></textarea><button onclick="test()">Append</button>
It is not possible to selectively mark parts of a <textarea> read-only, however, a similar effect can be achieved with contenteditable elements:
function test() {
const x = 'this is a string to be appended to text area'
const span = document.createElement('span')
span.appendChild(document.createTextNode(x))
span.setAttribute('contenteditable', 'false')
document.getElementById("textArea").appendChild(span);
}
#textArea{
border: 1px solid black;
height: 50px;
}
<div id="textArea" contenteditable="true"></div>
<button onclick="test()">Append</button>
However, this will still allow the user to delete the read-only block, or write before it.
This almost works.
EDIT:
Improved it a bit by changing keydown to keyup.
Now there is no need for space at the end of the read-only text and CTRL+a and then backspace will make the text come back almost instantly.
Maybe you can improve on it.
window.onload = function() {
document.getElementById('textArea').addEventListener('keyup', function (e){
var readOnlyLength = parseInt(document.getElementById("textArea").getAttribute('data-readOnlyLength') );
var currentLength = parseInt(document.getElementById("textArea").value.length );
if (readOnlyLength >= currentLength ) {
document.getElementById("textArea").value = document.getElementById("textArea").getAttribute('data-readonly') ;
}
}, false);
};
function test() {
x = 'this is a string to be appended to text area'
document.getElementById("textArea").value = x;
document.getElementById("textArea").setAttribute('data-readonly' , x);
document.getElementById("textArea").setAttribute('data-readOnlyLength' , x.length);
}
<textarea id="textArea"></textarea>
<button onclick="test()">Append</button>
I'm all new to this, but after spending a week trying to find an answer, I thought I would try asking directly.
I am building a text editor using javascript and jquery. I have a textarea (with contenteditable), a stylesheet and a js script. What I want is that for each letter pressed, the kerning will be random. I achieved that with a simple function, but I don't want ALL textarea text to have this kerning, only the last letter pressed and so on and so on, so this type of thing would be the result:
simulation
There is what I have so far in my js file:
$(document).ready(
function() {
$('#textarea').keypress(function(){
var KerningRandom = Math.floor((Math.random()*90)-20);
$(this).css('letter-spacing',KerningRandom);
});
Here is my jsfiddle that actually doesn't work in jsfiddle and I don't get why as it works fine in local...?
Thanks!
You cannot address individual characters ( and so glyphs ) in CSS. Only ::first-letter.
Options you have:
convert all characters to individual spans. That's too much I think.
use <canvas> to render text and so to implement text flow layout from scratch.
You can find a working plunker of what you want to achieve there (I forked yours).
https://jsfiddle.net/1gesLgsa/2/
Full code :
//Code from https://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity
//Namespace management idea from http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/
(function( cursorManager ) {
//From: http://www.w3.org/TR/html-markup/syntax.html#syntax-elements
var voidNodeTags = ['AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR', 'BASEFONT', 'BGSOUND', 'FRAME', 'ISINDEX'];
//From: https://stackoverflow.com/questions/237104/array-containsobj-in-javascript
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
//Basic idea from: https://stackoverflow.com/questions/19790442/test-if-an-element-can-contain-text
function canContainText(node) {
if(node.nodeType == 1) { //is an element node
return !voidNodeTags.contains(node.nodeName);
} else { //is not an element node
return false;
}
};
function getLastChildElement(el){
var lc = el.lastChild;
while(lc && lc.nodeType != 1) {
if(lc.previousSibling)
lc = lc.previousSibling;
else
break;
}
return lc;
}
//Based on Nico Burns's answer
cursorManager.setEndOfContenteditable = function(contentEditableElement)
{
while(getLastChildElement(contentEditableElement) &&
canContainText(getLastChildElement(contentEditableElement))) {
contentEditableElement = getLastChildElement(contentEditableElement);
}
var range,selection;
if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+
{
range = document.createRange();//Create a range (a range is a like the selection but invisible)
range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
selection = window.getSelection();//get the selection object (allows you to change selection)
selection.removeAllRanges();//remove any selections already made
selection.addRange(range);//make the range you have just created the visible selection
}
else if(document.selection)//IE 8 and lower
{
range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible)
range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
range.select();//Select the range (make it the visible selection
}
}
}( window.cursorManager = window.cursorManager || {}));
// ACTUAL CODE MADE FOR THIS ANSWER
$('#textarea').keypress(function(event) {
event.preventDefault();
var KerningRandom = Math.floor((Math.random() * 90));
if ($("#last").length > 0)
{
var previousLast = $("#textarea #last").html();
$("#textarea #last").remove();
}
else
var previousLast = "";
$("#textarea").html($("#textarea").html().slice() + previousLast + "<span id='last'>" + String.fromCharCode(event.which) + "</span>")
$("#last").css('margin-left', KerningRandom + "px");
var editableDiv = document.getElementById("textarea");
cursorManager.setEndOfContenteditable(editableDiv)
});
var editableDiv = document.getElementById("textarea");
cursorManager.setEndOfContenteditable(editableDiv)
Point by point explanation :
$('#textarea').keypress(function(event) {
event.preventDefault();
var KerningRandom = Math.floor((Math.random() * 90));
if ($("#last").length > 0)
{
var previousLast = $("#textarea #last").html();
$("#textarea #last").remove();
}
else
var previousLast = "";
$("#textarea").html($("#textarea").html() + previousLast + "<span id='last'>" + String.fromCharCode(event.which) + "</span>")
$("#last").css('margin-left', KerningRandom + "px");
var editableDiv = document.getElementById("textarea");
cursorManager.setEndOfContenteditable(editableDiv)
});
The event.preventDefault() prevent the letter to be added when pressing a key.
Then, we calculate our left margin value, save the previous last letter we had and remove the span that contains the last letter as it's not the last letter anymore.
We append the previous last letter , and the span that has a random left margin (to simulate the kerning) and the value of the pressed key (thanks to
How to find out what character key is pressed?) to the actual content.
After that, we needed to move the carret at the end of the textarea manually, because it would stay at the beginning otherwise.
For that, I used the code from
How to move cursor to end of contenteditable entity so goes there for explanation.
I have a function that I want to change the font color of the user entered string if it is equal to a certain word located in an array.. So far when I step through it it says that it changes the font color but it actually never updates it to the screen and I don't know why. Here is what I have so far
function getLastWord() {
var input = document.getElementById("my_text");
//var input = document.getElementById(textArea.value);
//var lineIn = document.getElementById(my_text).innerHTML;
var inputValue = input.value;
var lastWordTyped
var changeColorOfWord;
if (input == null) {
input == " ";
}
//lastWordTyped = input.substr(input.trim().lastIndexOf(" ") + 1);
lastWordTyped = inputValue.substr(inputValue.trim().lastIndexOf(" ") + 1);
if (input != null) {
for (var i = 0; i < reservedKeyWords.length; i++) {
if (reservedKeyWords[i] === lastWordTyped) {
lastWordTyped = lastWordTyped.fontcolor("blue");
my_text.replace(inputValue, lastWordTyped);
} else {
}
}
}
}
I see two issues with the code thus far.
You are using 'fontcolor("blue")' parameter on the lastWordTyped. The proper syntax to change color is element.style.color="#CCC".
You will need to wrap the last typed word in a span so you can target it and apply the color to just that word.
string.fontcolor is legacy, and should not be used even though I could see it as a viable option in this case
Essentially, what you are doing is adding font tags around the word:
var txt = 'hello world';
txt = txt.fontcolor('blue');
//txt = '<font color="blue">hello world</font>';
You do not show what you do with the result, but if you actually put it in an HTML element it should work, even though instead of using fontcolor, I'd rather use element.style.color. This would require slightly more work though:
var ele = document.querySelector('#my_text');
ele.style.color = 'blue';
ele.innerHTML = lastWordTyped;
If you still want to go with the .fontcolor method, you could just keep what you have in the question and add
input.innerHTML = my_text;
i need to highlight all the occurrences of a string in particular div by selecting a string,
once i select a word and click a button it need to highlight all its occurrence inside a div,
eg - if i select
cricket is game
it should highlight all the occurrences of cricket is game some may be like this cricket is game or cricket is game
You can get the browser to do the hard work for you using a TextRange in IE and window.find() in other browsers.
This answer shows how to do it. It will match text that crosses element boundaries and does the highlighting for you using document.execCommand().
Alternatively, James Padolsey recently published a script that I haven't used but looks like it could help: http://james.padolsey.com/javascript/replacing-text-in-the-dom-solved/
mark.js seems pretty good for this. Here's my 3 line fiddle to take an html 'string' and highlight the search string.
$(document).ready(function() {
var html_string = "<b>Major Tom to groundcontrol.</b> Earth is blue <span> and there's something </span> i can do";
var with_highlight = $("<div/>").html(html_string).mark("can");
$("#msg").html(with_highlight);
})
Link to jsfiddle
You can tryout this script Demo
in highlightSearchTerms function of this script var bodyText = document.body.innerHTML; get replace by your divid and than it will do the task for you..
/*
* This is the function that actually highlights a text string by
* adding HTML tags before and after all occurrences of the search
* term. You can pass your own tags if you'd like, or if the
* highlightStartTag or highlightEndTag parameters are omitted or
* are empty strings then the default <font> tags will be used.
*/
function doHighlight(bodyText, searchTerm, highlightStartTag, highlightEndTag)
{
// the highlightStartTag and highlightEndTag parameters are optional
if ((!highlightStartTag) || (!highlightEndTag)) {
highlightStartTag = "<font style='color:blue; background-color:yellow;'>";
highlightEndTag = "</font>";
}
// find all occurences of the search term in the given text,
// and add some "highlight" tags to them (we're not using a
// regular expression search, because we want to filter out
// matches that occur within HTML tags and script blocks, so
// we have to do a little extra validation)
var newText = "";
var i = -1;
var lcSearchTerm = searchTerm.toLowerCase();
var lcBodyText = bodyText.toLowerCase();
while (bodyText.length > 0) {
i = lcBodyText.indexOf(lcSearchTerm, i+1);
if (i < 0) {
newText += bodyText;
bodyText = "";
} else {
// skip anything inside an HTML tag
if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
// skip anything inside a <script> block
if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
newText += bodyText.substring(0, i) + highlightStartTag + bodyText.substr(i, searchTerm.length) + highlightEndTag;
bodyText = bodyText.substr(i + searchTerm.length);
lcBodyText = bodyText.toLowerCase();
i = -1;
}
}
}
}
return newText;
}
/*
* This is sort of a wrapper function to the doHighlight function.
* It takes the searchText that you pass, optionally splits it into
* separate words, and transforms the text on the current web page.
* Only the "searchText" parameter is required; all other parameters
* are optional and can be omitted.
*/
function highlightSearchTerms(searchText, treatAsPhrase, warnOnFailure, highlightStartTag, highlightEndTag)
{
// if the treatAsPhrase parameter is true, then we should search for
// the entire phrase that was entered; otherwise, we will split the
// search string so that each word is searched for and highlighted
// individually
if (treatAsPhrase) {
searchArray = [searchText];
} else {
searchArray = searchText.split(" ");
}
if (!document.body || typeof(document.body.innerHTML) == "undefined") {
if (warnOnFailure) {
alert("Sorry, for some reason the text of this page is unavailable. Searching will not work.");
}
return false;
}
var bodyText = document.body.innerHTML;
for (var i = 0; i < searchArray.length; i++) {
bodyText = doHighlight(bodyText, searchArray[i], highlightStartTag, highlightEndTag);
}
document.body.innerHTML = bodyText;
return true;
}
/*
* This displays a dialog box that allows a user to enter their own
* search terms to highlight on the page, and then passes the search
* text or phrase to the highlightSearchTerms function. All parameters
* are optional.
*/
function searchPrompt(defaultText, treatAsPhrase, textColor, bgColor)
{
// This function prompts the user for any words that should
// be highlighted on this web page
if (!defaultText) {
defaultText = "";
}
// we can optionally use our own highlight tag values
if ((!textColor) || (!bgColor)) {
highlightStartTag = "";
highlightEndTag = "";
} else {
highlightStartTag = "<font style='color:" + textColor + "; background-color:" + bgColor + ";'>";
highlightEndTag = "</font>";
}
if (treatAsPhrase) {
promptText = "Please enter the phrase you'd like to search for:";
} else {
promptText = "Please enter the words you'd like to search for, separated by spaces:";
}
searchText = prompt(promptText, defaultText);
if (!searchText) {
alert("No search terms were entered. Exiting function.");
return false;
}
return highlightSearchTerms(searchText, treatAsPhrase, true, highlightStartTag, highlightEndTag);
}
This should get you started: http://jsfiddle.net/wDN5M/
function getSelText() {
var txt = '';
if (window.getSelection) {
txt = window.getSelection();
} else if (document.getSelection) {
txt = document.getSelection();
} else if (document.selection) {
txt = document.selection.createRange().text;
}
document.getElementById('mydiv').innerHTML = document.getElementById('mydiv').innerHTML.split(txt).join('<span class="highlight">' + txt + '</span>');
}
See: Get selected text on the page (not in a textarea) with jQuery
If you want it to work across element boundaries your code will need to be more involved than this. jQuery will make your life easier when doing the necessary DOM traversal and manipulation.
I would use jQuery to iterate over all Elements in your div (Don't know if you have other elements in the div) and then a Regular Expression and do a greedy match to find all occurrences of the selected string in your text(s) in the elements.
First you need to find needed substrings in needed text and wrap them with <span class="search-highlight">. Every time you need to highlight another strings, you just get all the .search-highlight spans and turn their outerHtml into innerHtml.
So the code will be close to:
function highLight(substring, block) {
$(block).find(".search-highlight").each(function () {
$(this).outerHtml($(this).html());
});
// now the block is free from previous highlights
$(block).html($(block).html().replace(/substring/g, '<span class="search-highlight">' + substring + '</span>'));
}
<form id=f1 name="f1" action=""
onSubmit="if(this.t1.value!=null && this.t1.value!='')
findString(this.t1.value);return false"
>
<input type="text" id=t1 name=t1size=20>
<input type="submit" name=b1 value="Find">
</form>
<script>
var TRange=null;
function findString (str) {
if (parseInt(navigator.appVersion)<4) return;
var strFound;
if (window.find) {
// CODE FOR BROWSERS THAT SUPPORT window.find
strFound=self.find(str);
if (!strFound) {
strFound=self.find(str,0,1);
while (self.find(str,0,1)) continue;
}
}
else if (navigator.appName.indexOf("Microsoft")!=-1) {
// EXPLORER-SPECIFIC CODE
if (TRange!=null) {
TRange.collapse(false);
strFound=TRange.findText(str);
if (strFound) TRange.select();
}
if (TRange==null || strFound==0) {
TRange=self.document.body.createTextRange();
strFound=TRange.findText(str);
if (strFound) TRange.select();
}
}
else if (navigator.appName=="Opera") {
alert ("Opera browsers not supported, sorry...")
return;
}
if (!strFound) alert ("String '"+str+"' not found!")
return;
}
</script>
Much better to use rather JavaScript str.replace() function then window.find() to find all occurrences of a filter value. Iterating through the whole page might be bit complicated but if you want to search within a parent div, or within a table str.replace() is just simpler.
In your example you have only one DIV, that is even simpler. Here is what I would do (having your DIV an ID: myDIV):
//Searching for "District Court"
var filter = "District Court";
//Here we create the highlight with html tag: <mark> around filter
var span = '<mark>' + filter + '</mark>';
//take the content of the DIV you want to highlight
var searchInthisDiv = document.getElementById("MyDiv");
var textInDiv = searchInthisDiv.innerHTML;
//needed this var for replace function, do the replace (the highlighting)
var highlighted = textInDiv.replace(filter,span);
textInDiv.innerHTML = highlighted;
The trick is to replace the search string with a span that is having the filter within a tag.
str.replace replaces all occurrences of the search string, so no need to bother with looping. Loop can be used to loop through DIVs or other DOM elements.
I am using a 'contenteditable' <div/> and enabling PASTE.
It is amazing the amount of markup code that gets pasted in from a clipboard copy from Microsoft Word. I am battling this, and have gotten about 1/2 way there using Prototypes' stripTags() function (which unfortunately does not seem to enable me to keep some tags).
However, even after that, I wind up with a mind-blowing amount of unneeded markup code.
So my question is, is there some function (using JavaScript), or approach I can use that will clean up the majority of this unneeded markup?
Here is the function I wound up writing that does the job fairly well (as far as I can tell anyway).
I am certainly open for improvement suggestions if anyone has any. Thanks.
function cleanWordPaste( in_word_text ) {
var tmp = document.createElement("DIV");
tmp.innerHTML = in_word_text;
var newString = tmp.textContent||tmp.innerText;
// this next piece converts line breaks into break tags
// and removes the seemingly endless crap code
newString = newString.replace(/\n\n/g, "<br />").replace(/.*<!--.*-->/g,"");
// this next piece removes any break tags (up to 10) at beginning
for ( i=0; i<10; i++ ) {
if ( newString.substr(0,6)=="<br />" ) {
newString = newString.replace("<br />", "");
}
}
return newString;
}
Hope this is helpful to some of you.
You can either use the full CKEditor which cleans on paste, or look at the source.
I am using this:
$(body_doc).find('body').bind('paste',function(e){
var rte = $(this);
_activeRTEData = $(rte).html();
beginLen = $.trim($(rte).html()).length;
setTimeout(function(){
var text = $(rte).html();
var newLen = $.trim(text).length;
//identify the first char that changed to determine caret location
caret = 0;
for(i=0;i < newLen; i++){
if(_activeRTEData[i] != text[i]){
caret = i-1;
break;
}
}
var origText = text.slice(0,caret);
var newText = text.slice(caret, newLen - beginLen + caret + 4);
var tailText = text.slice(newLen - beginLen + caret + 4, newLen);
var newText = newText.replace(/(.*(?:endif-->))|([ ]?<[^>]*>[ ]?)|( )|([^}]*})/g,'');
newText = newText.replace(/[ยท]/g,'');
$(rte).html(origText + newText + tailText);
$(rte).contents().last().focus();
},100);
});
body_doc is the editable iframe, if you are using an editable div you could drop out the .find('body') part. Basically it detects a paste event, checks the location cleans the new text and then places the cleaned text back where it was pasted. (Sounds confusing... but it's not really as bad as it sounds.
The setTimeout is needed because you can't grab the text until it is actually pasted into the element, paste events fire as soon as the paste begins.
How about having a "paste as plain text" button which displays a <textarea>, allowing the user to paste the text in there? that way, all tags will be stripped for you. That's what I do with my CMS; I gave up trying to clean up Word's mess.
You can do it with regex
Remove head tag
Remove script tags
Remove styles tag
let clipboardData = event.clipboardData || window.clipboardData;
let pastedText = clipboardData.getData('text/html');
pastedText = pastedText.replace(/\<head[^>]*\>([^]*)\<\/head/g, '');
pastedText = pastedText.replace(/\<script[^>]*\>([^]*)\<\/script/g, '');
pastedText = pastedText.replace(/\<style[^>]*\>([^]*)\<\/style/g, '');
// pastedText = pastedText.replace(/<(?!(\/\s*)?(b|i|u)[>,\s])([^>])*>/g, '');
here the sample : https://stackblitz.com/edit/angular-u9vprc
I did something like that long ago, where i totally cleaned up the stuff in a rich text editor and converted font tags to styles, brs to p's, etc, to keep it consistant between browsers and prevent certain ugly things from getting in via paste. I took my recursive function and ripped out most of it except for the core logic, this might be a good starting point ("result" is an object that accumulates the result, which probably takes a second pass to convert to a string), if that is what you need:
var cleanDom = function(result, n) {
var nn = n.nodeName;
if(nn=="#text") {
var text = n.nodeValue;
}
else {
if(nn=="A" && n.href)
...;
else if(nn=="IMG" & n.src) {
....
}
else if(nn=="DIV") {
if(n.className=="indent")
...
}
else if(nn=="FONT") {
}
else if(nn=="BR") {
}
if(!UNSUPPORTED_ELEMENTS[nn]) {
if(n.childNodes.length > 0)
for(var i=0; i<n.childNodes.length; i++)
cleanDom(result, n.childNodes[i]);
}
}
}
This works great to remove any comments from HTML text, including those from Word:
function CleanWordPastedHTML(sTextHTML) {
var sStartComment = "<!--", sEndComment = "-->";
while (true) {
var iStart = sTextHTML.indexOf(sStartComment);
if (iStart == -1) break;
var iEnd = sTextHTML.indexOf(sEndComment, iStart);
if (iEnd == -1) break;
sTextHTML = sTextHTML.substring(0, iStart) + sTextHTML.substring(iEnd + sEndComment.length);
}
return sTextHTML;
}
Had a similar issue with line-breaks being counted as characters and I had to remove them.
$(document).ready(function(){
$(".section-overview textarea").bind({
paste : function(){
setTimeout(function(){
//textarea
var text = $(".section-overview textarea").val();
// look for any "\n" occurences and replace them
var newString = text.replace(/\n/g, '');
// print new string
$(".section-overview textarea").val(newString);
},100);
}
});
});
Could you paste to a hidden textarea, copy from same textarea, and paste to your target?
Hate to say it, but I eventually gave up making TinyMCE handle Word crap the way I want. Now I just have an email sent to me every time a user's input contains certain HTML (look for <span lang="en-US"> for example) and I correct it manually.