admin管理员组文章数量:1321037
Oddly specific question, but I have a solution already to paste plain text in a <span contentEditable="true">
by using a hidden textarea
, which seems to work really well, except that it breaks the browser's undo feature. Right off the bat I'm not worried about a cross-browser solution; I only care about Chrome. My approach looks roughly like this:
$('.editable').live('paste', function()
{
var $this = $(this);
//more code here to remember caret position, etc
$('#clipboard').val('').focus(); //put the focus in the hidden textarea so that, when the paste actually occurs, it's auto-sanitized by the textarea
setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
$this.focus();
document.execCommand('insertHTML', true, $('#clipboard').val());
});
});
So this works -- I can paste anything and it's reduced to plain text before going into the my contentEditable
field -- but if I try to undo after pasting:
- First undo undoes the paste.
- Second undo tries to undo the changes to
#clipboard
, moving the focus away from mycontentEditable
.
I've tried everything I can think of to make the browser not try to undo the changes to #clipboard
-- toggling display:none
when it's not actively in use, toggling readonly
and disabled
state, destroying it at the end of and recreating it at the beginning of the event above, various other hacks -- but nothing seems to work.
Is this a terrible approach to sanitization? This is the first thing I've managed to really get working -- trying to clean up the markup after the paste occurs didn't work, as there are some things (entire HTML documents) which, when pasted, crash the browser, which I'd like to avoid.
Is there any way to make the #clipboard
not undoable, or any other suggestions of how to get this working?
Edit
I managed to improve things a little bit by adding the line
$('#clipboard').val('');
Right after the execCommand
line. This seems to neutralize undo pletely: the caret no longer leaves the contentEditable
field, but nothing gets undone at all. A bit of an improvement, but I'm still searching for a proper solution.
Oddly specific question, but I have a solution already to paste plain text in a <span contentEditable="true">
by using a hidden textarea
, which seems to work really well, except that it breaks the browser's undo feature. Right off the bat I'm not worried about a cross-browser solution; I only care about Chrome. My approach looks roughly like this:
$('.editable').live('paste', function()
{
var $this = $(this);
//more code here to remember caret position, etc
$('#clipboard').val('').focus(); //put the focus in the hidden textarea so that, when the paste actually occurs, it's auto-sanitized by the textarea
setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
$this.focus();
document.execCommand('insertHTML', true, $('#clipboard').val());
});
});
So this works -- I can paste anything and it's reduced to plain text before going into the my contentEditable
field -- but if I try to undo after pasting:
- First undo undoes the paste.
- Second undo tries to undo the changes to
#clipboard
, moving the focus away from mycontentEditable
.
I've tried everything I can think of to make the browser not try to undo the changes to #clipboard
-- toggling display:none
when it's not actively in use, toggling readonly
and disabled
state, destroying it at the end of and recreating it at the beginning of the event above, various other hacks -- but nothing seems to work.
Is this a terrible approach to sanitization? This is the first thing I've managed to really get working -- trying to clean up the markup after the paste occurs didn't work, as there are some things (entire HTML documents) which, when pasted, crash the browser, which I'd like to avoid.
Is there any way to make the #clipboard
not undoable, or any other suggestions of how to get this working?
Edit
I managed to improve things a little bit by adding the line
$('#clipboard').val('');
Right after the execCommand
line. This seems to neutralize undo pletely: the caret no longer leaves the contentEditable
field, but nothing gets undone at all. A bit of an improvement, but I'm still searching for a proper solution.
- Why reinvent the wheel? Since you're already using jQuery, why not just use a plugin like markItUp! or TinyMCE? – Matt Ball Commented Feb 23, 2011 at 5:20
-
@Matt - neither of those do what I'm asking. markItUp! uses a textarea -- nothing
contentEditable
there -- and TinyMCE allows pasting all kinds of markup. I'm not trying to make a rich text editor -- just the opposite, in fact. I'm trying to make a plain textcontentEditable
element. Just use atextarea
, right? Would love to, but I need the content to wrap around other elements in the page. – Ian Henry Commented Feb 23, 2011 at 7:04 - "markItUp! uses a textarea" — erm... It is much simpler to change it, than writing own from scratch, isn't it? – kirilloid Commented Feb 23, 2011 at 9:11
-
2
@kirilloid: Not really. The mechanisms for dealing with selections and updating content are so pletely different in
<textareas>
andcontenteditable
elements that switching between the two would require a plete rewrite. – Tim Down Commented Feb 23, 2011 at 9:22 - 3 Sounds to me like you might have to create your own undo mechanism. – Tim Down Commented Feb 23, 2011 at 9:45
4 Answers
Reset to default 1CodeMirror 1 does this by stripping away formatting after text is pasted. CodeMirror 2 does this by actually having an invisible textarea handle everything, and render the text and cursor manually.
CodeMirror's website describes how it works in more detail: http://codemirror/internals.html
Beyond that, there's always the CodeMirror source code. You can decide for yourself whether CodeMirror 1 or CodeMirror 2's approach is more suitable for your purposes. :)
Do you try that?
setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
$this.focus();
document.execCommand('insertHTML', true, $('#clipboard').val());
var t = document.body.innerHTML;
document.execCommand("undo");
document.body.innerHTML = t;
});
I think it can help. But I think you must use event object. Unfortunately there may be a problem cuz security reasons.
In onpaste:
Store the current selection.
var sel = window.getSelection(); var range = selObj.getRangeAt(0).cloneRange; // Store the range object somewhere.
Modify the selection object to point to your hidden textarea.
Set a timeout with a delay of 0 (occurs immediately after paste).
In the timeout function, grab the data from the hidden textarea, then:
var sel = window.getSelection(); sel.removeAllRanges(); var range = // restore the range object from before. sel.addRange(range); document.execCommand("insertHTML", false, /* contents of your textarea here */);
Now if you wanted to do this for actual HTML content, you'd be in a world of hurt....
Insert a <pre contenteditable="true">...</pre>
. As I recall that's exactly what I understand you want. (Unfortunately I'm not yet allowed to join everyone in the ments, but I suppose this is an attempt to answer anyway.)
版权声明:本文标题:javascript - How can I make a plain text paste in a contentEditable span without breaking undo? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742095121a2420499.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论