欢迎各位兄弟 发布技术文章
这里的技术是共享的
真巧,前几天上线的知乎编辑器代码插件,有纯文本粘贴这个特性在里面。
JavaScript 是完全可以做到的!趁记忆未冷,总结一下:
W3C 标准下的做法(webkit/opera):
使用:
Clipboard API and eventsclipboardData.getData('text/plain')
getData 方法接收一个 MIME 类型,比如你粘贴图片时可能是 image/png,粘贴富文本时可能是 text/html 和 text/plain 两种,支持的类型可以在 clipboardData.types 里面查询。
IE 下的做法:
IE 在这里其实很值得称赞,只是它支持的时候 W3C 标准还没有,所以只能用 Text 参数:
clipboardData.getData('Text')
在把选区内容替换成获取到的文本时,要注意两个问题:
一 CRLF
Windows 风格的换行是 \r,而其他系统是 \n,有两种方法获得处理一致的换行效果(以 Closure Library 为例):
* canonicalizeNewlines
canonicalizeNewlines = (str) -> str.replace(/(\r\n|\r|\n)/g, '\n')
* newLineToBr
newLineToBr = (str) -> str.replace(/(\r\n|\r|\n)/g, '<br>')
二 TextRange::pasteHTML
W3C 下可以用 Range::insertNode 获取插入对象的引用,但 IE 只能插入一个字符串,如果直接插入带换行的纯文本,这样换行就会丢失,因此实现了这样一个 hack(createHolder_ 函数辅助了这一过程):1)生成并插入一个占位元素 2)检索占位元素 3)替换占位元素为指定文本节点。
plugin.replaceTextIE = function(range, text) {
this.createHolder_('i', function(holder, retrieve) {
range.replaceContentsWithNode(holder)
holder = retrieve()
text = goog.string.canonicalizeNewlines(text)
goog.dom.replaceNode(document.createTextNode(text), holder)
})
}
Firefox 下的做法:
正常途径下获取不到剪贴板内容,需要实现一个 textFromHtml 函数。
代码插件是在 <code> 标签内部粘贴时去除格式,因此这样简单地处理就可以了:
code.textContent = textFromHtml(code.innerHTML)
如果要任意区域实现纯文本粘贴,我的建议是:
1)paste 事件发生之时,在选区起点之前和终点之后插入占位元素;
2)paste 之后(比如 setTimeout),获取两个占位元素中间的内容——即粘贴的内容;
3)转换粘贴的内容为纯文本;
附代码插件源码(
editor_plugin_code.js)片断:
plugin.handlePaste_ = function(e) {
var _ = this.getStateTuple(), state = _.state, range = _.range, code = _.code
if (state !== Plugin.State.EDITABLE) return
var text, textType = 'text/plain'
var clipboard = e.getBrowserEvent().clipboardData
if (clipboard) { // w3c(webkit,opera...)
if (clipboard.types && goog.array.contains(clipboard.types, textType)) {
e.preventDefault()
text = clipboard.getData(textType)
this.replaceText(range, text)
}
} else if (window.clipboardData) { // IE
text = window.clipboardData.getData('Text')
if (text) {
e.preventDefault()
this.replaceTextIE(range, text)
}
} else { // FF
// TODO:rewrite
var offset = range.getStartOffset()
var selectedLength = range.getText().length
var codeLength = function() {
return code.firstChild ? goog.editor.node.getLength(code.firstChild) : 0
}
var endLength = codeLength() - offset - selectedLength
setTimeout(function() {
Plugin.cleanup(code)
var caretOffset = codeLength() - endLength
if (code.firstChild) {
goog.dom.Range.createCaret(code.firstChild, Math.max(offset, caretOffset)).select()
}
})
}
}
单纯的 JavaScript 没有一个很完美的访问剪贴板(Clipboard)的方案。
和 jQuery 更是没有直接关系。
更多是采用 invisible Flash 技术来桥接粘贴功能。
推荐看下这个:
https://code.google.com/p/zeroclipboard/var copyText = document.getElementById("myInput");
copyText.select();
document.execCommand("copy");
console.log(copyText.value);
来自 https://www.zhihu.com/question/20747877