-
-
Save liushooter/1254a8d989b1b1f4807b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Clipboard.js | |
* | |
* Copyright, Moxiecode Systems AB | |
* Released under LGPL License. | |
* | |
* License: http://www.tinymce.com/license | |
* Contributing: http://www.tinymce.com/contributing | |
*/ | |
/** | |
* This class contains logic for getting HTML contents out of the clipboard. | |
* | |
* @class lwbeditor.paste.Clipboard | |
* @private | |
*/ | |
define("editor/plugs/paste/Clipboard", function(require) { | |
var utils = require('utils'); | |
var plugs = require('plugs'); | |
var Env = require('Env'); | |
var VK = require('VK'); | |
var $ = require('$'); | |
function hasClipboardData() { | |
// Gecko is excluded until the fix: https://bugzilla.mozilla.org/show_bug.cgi?id=850663 | |
return !Env.gecko && (("ClipboardEvent" in window) || (Env.webkit && "FocusEvent" in window)); | |
} | |
function Clipboard(editor) { | |
var self = this, plainTextPasteTime; | |
function now() { | |
return new Date().getTime(); | |
} | |
function isPasteKeyEvent(e) { | |
// Ctrl+V or Shift+Insert | |
return (VK.metaKeyPressed(e) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45); | |
} | |
function innerText(elm) { | |
return elm.innerText || elm.textContent; | |
} | |
function shouldPasteAsPlainText() { | |
return now() - plainTextPasteTime < 100 || self.pasteFormat == "text"; | |
} | |
// TODO: Move this to a class? | |
function process(content, items) { | |
utils.each(items, function(v) { | |
if (v.constructor == RegExp) { | |
content = content.replace(v, ''); | |
} else { | |
content = content.replace(v[0], v[1]); | |
} | |
}); | |
return content; | |
} | |
function processHtml(html) { | |
// console.log('粘贴的HTML:', html); | |
var args = {content: html}; | |
editor.trigger('PastePreProcess', args); | |
var content = args.content; | |
// console.log('过滤的HTML:', content); | |
content = content.replace(/[\u0020|\u3000]+/g, ' '); | |
// .replace(/<([^> ])(?: [^>]*)*>\s*<\/\1>/g, ''); chrome执行此表达式会出现问题。。。浏览器假死!! | |
// console.log('空格空标签:', content); | |
content = content.replace(/<br>|<BR>/g,'\n').replace(/\r\n/g, '\n').replace(/(\n)\1+/g,'\n'); | |
var ps = content.split(/\n/g); | |
var output = ''; | |
if(ps.length > 1){ | |
for(var i=0;i<ps.length;i++){ | |
output += '<p>'+ps[i]+'</p>'; | |
} | |
}else{ | |
output = content; | |
} | |
content = utils.filter(output, { | |
'p':[] | |
//'strong':[], | |
//'em':[], | |
//'blockquote':[] | |
}, true); | |
// console.log('processHtml',content); | |
editor.insertContent(content); | |
} | |
// 处理纯文本格式 | |
function processText(text) { | |
text = editor.dom.encode(text).replace(/\r\n/g, '\n').replace(/(\n)\1+/g,'\n'); | |
//var selection = editor.getSelection(); | |
//var rng = editor.getRange(); | |
//var startBlock = editor.dom.getParent(rng.startContainer, editor.dom.isBlock); | |
//text = text.replace(/&/g, '&').replace(/(<|>)/g, function(m){if('<' === m) return '<'; else return '>';}); | |
/* | |
if ((startBlock && (/^(PRE|DIV)$/).test(startBlock.nodeName)) || !editor.options.forced_root_block) { | |
text = process(text, [[(/\n/g), "<br>"]]); | |
} else { | |
text = process(text, [ | |
[(/\n\n/g), "</p><p>"], | |
[(/^(.*<\/p>)(<p>)$/), '<p>$1'], | |
[(/\n/g), "<br />"] | |
]); | |
} | |
*/ | |
var ps = text.split(/\n/g); | |
var output = ''; | |
for(var i=0;i<ps.length;i++){ | |
output += '<p>'+ps[i]+'</p>'; | |
} | |
var args = { | |
content: output, | |
plainText: true | |
}; | |
editor.trigger('PastePreProcess', args); | |
editor.insertContent(args.content); | |
} | |
// 创建粘贴代理节点,存储粘贴的内容 | |
function createPasteBin() { | |
var vp = editor.dom.getViewPort(); | |
var scrollTop = vp.y; | |
var frag = editor.doc.createDocumentFragment(); | |
// Create a pastebin and move the selection into the bin | |
var pastebinElm = editor.dom.add(editor.getRoot(), 'div', { | |
contentEditable: false, | |
"data-mce-bogus": "1", | |
style: 'position: absolute; top: '+scrollTop+'px; left: 0;border: none; width: 1px; height: 1px; overflow: hidden' | |
}, '<div contenteditable="true" data-mce-bogus="1">X</div>'); | |
editor.dom.bind(pastebinElm, 'beforedeactivate focusin focusout', function(e) { | |
e.stopPropagation(); | |
}); | |
return pastebinElm; | |
} | |
// 删除粘贴代理节点 | |
function removePasteBin(pastebinElm) { | |
editor.dom.unbind(pastebinElm); | |
editor.dom.remove(pastebinElm); | |
} | |
// 粘贴时是否需要忽略过滤 | |
function isPastePass(evt) { | |
var tagName = evt.target.nodeName.toLowerCase(); | |
// 图注需要更改一下 | |
return (tagName === 'input' || tagName === 'textarea' || tagName === 'div'); | |
} | |
function clipboradPaste(self, e) { | |
//e = e.originalEvent || e; | |
var clipboardData = e.originalEvent.clipboardData; | |
function processByContentType(contentType, processFunc) { | |
for (var ti = 0; ti < clipboardData.types.length; ti++) { | |
if (clipboardData.types[ti] == contentType) { | |
processFunc(clipboardData.getData(contentType)); | |
//clipboardData.items[ti].getAsString(processFunc); | |
return true; | |
} | |
} | |
return false; | |
} | |
// 粘贴过滤处理 | |
if (clipboardData) { | |
e.preventDefault(); | |
if (shouldPasteAsPlainText()) { | |
// First look for HTML then look for plain text | |
if (!processByContentType('text/plain', processText)) { | |
processByContentType('text/html', processHtml); | |
} | |
} else { | |
// First look for HTML then look for plain text | |
if (!processByContentType('text/html', processHtml)) { | |
processByContentType('text/plain', processText); | |
} | |
} | |
} | |
} | |
editor.on('keydown', function(e) { | |
// Shift+Ctrl+V | |
if (VK.metaKeyPressed(e) && e.shiftKey && e.keyCode == 86) { | |
plainTextPasteTime = now(); | |
} | |
}); | |
// Use Clipboard API if it's available | |
if (hasClipboardData()) { | |
editor.on('paste', function(self, e) { | |
if (isPastePass(e)) { | |
return; | |
} | |
clipboradPaste(self, e); | |
}); | |
} else { | |
if (Env.ie) { | |
var keyPasteTime = 0; | |
editor.on('keydown', function(e) { | |
if (isPasteKeyEvent(e) && !e.isDefaultPrevented()) { | |
if (isPastePass(e)) { | |
return; | |
} | |
var pastebinElm = createPasteBin(); | |
keyPasteTime = now(); | |
// 获取html值 | |
setTimeout(function() { | |
editor.setRng(lastRng); | |
var html = childElm.innerHTML; | |
removePasteBin(pastebinElm); | |
processHtml(childElm.innerHTML); | |
}, 0); | |
var lastRng = editor.getRange(); | |
var childElm = pastebinElm.firstChild; | |
childElm.focus(); | |
childElm.innerText = ''; | |
var rng = editor.doc.body.createTextRange(); | |
rng.moveToElementText(childElm); | |
rng.select(); | |
//rng.execCommand('Paste'); | |
e.cancelBubble = true; | |
e.returnValue = false; | |
} | |
}); | |
// Explorer fallback | |
editor.on('init', function() { | |
var dom = editor.dom; | |
// Use a different method if the paste was made without using the keyboard | |
// for example using the browser menu items | |
dom.bind(editor.getRoot(), 'paste', function(e) { | |
e.preventDefault(); | |
if (now() - keyPasteTime > 100) { | |
var gotPasteEvent, pastebinElm = createPasteBin(); | |
dom.bind(pastebinElm, 'paste', function(e) { | |
e.stopPropagation(); | |
gotPasteEvent = true; | |
}); | |
var lastRng = editor.getRange(); | |
// Select the container | |
var childElm = pastebinElm.firstChild; | |
var rng = dom.doc.body.createTextRange(); | |
childElm.focus(); | |
childElm.innerText = ''; | |
rng.moveToElementText(pastebinElm.firstChild); | |
rng.select(); | |
rng.execCommand('Paste'); | |
removePasteBin(pastebinElm); | |
if (!gotPasteEvent) { | |
alert('请使用Ctrl+V/Cmd+V进行粘贴.'); | |
return; | |
} | |
editor.setRng(lastRng); | |
if (shouldPasteAsPlainText()) { | |
processText(innerText(pastebinElm.firstChild)); | |
} else { | |
processHtml(pastebinElm.firstChild.innerHTML); | |
} | |
} | |
}); | |
}); | |
} else { | |
editor.on('init', function() { | |
editor.dom.bind(editor.getRoot(), 'paste', function(e) { | |
if (isPastePass(e)) { | |
return; | |
} | |
clipboradPaste(self, e); | |
}); | |
}); | |
// Old Gecko/WebKit/Opera fallback | |
editor.on('keydown', function(e) { | |
var tagName = e.target.nodeName.toLowerCase(); | |
var filter = (tagName === 'input' || tagName === 'textarea'); | |
if (isPasteKeyEvent(e) && !e.isDefaultPrevented() && !filter) { | |
// Prevent undoManager keydown handler from making an undo level with the pastebin in it | |
e.stopImmediatePropagation(); | |
var pastebinElm = createPasteBin(); | |
var lastRng = editor.getRange(); | |
editor.select(pastebinElm, true); | |
editor.dom.bind(pastebinElm, 'paste', function(e) { | |
e.stopPropagation(); | |
setTimeout(function() { | |
removePasteBin(pastebinElm); | |
editor.lastRng = lastRng; | |
editor.setRng(lastRng); | |
var pastebinContents = pastebinElm.firstChild; | |
// Remove last BR Safari on Mac adds trailing BR | |
if (pastebinContents.lastChild && pastebinContents.lastChild.nodeName == 'BR') { | |
pastebinContents.removeChild(pastebinContents.lastChild); | |
} | |
// MsoNormal | |
// <p class="MsoNormal" style="text-align:left;text-indent:21.0pt" align="left"><span lang="EN-US">Tesla</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; | |
// mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: | |
// minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">汽车似乎已经创造了一副极其吸引人的“未来科幻般的”汽车使用场景,并且脚踏实地地将这样一幅场景逐步变为现实。</span></p> | |
if (shouldPasteAsPlainText()) { | |
processText(innerText(pastebinContents)); | |
} else { | |
processHtml(pastebinContents.innerHTML); | |
} | |
}, 0); | |
}); | |
} | |
}); | |
} | |
// Prevent users from dropping data images on Gecko | |
if (!editor.options.paste_data_images) { | |
editor.on('drop', function(e) { | |
var dataTransfer = e.dataTransfer; | |
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { | |
e.preventDefault(); | |
} | |
}); | |
} | |
} | |
// Block all drag/drop events | |
if (editor.paste_block_drop) { | |
editor.on('dragend dragover draggesture dragdrop drop drag', function(e) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
}); | |
} | |
this.paste = processHtml; | |
this.pasteText = processText; | |
} | |
return Clipboard; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment