Skip to content

Instantly share code, notes, and snippets.

@liushooter
Forked from xiaojue/clipboard.js
Last active August 29, 2015 14:24
Show Gist options
  • Save liushooter/1254a8d989b1b1f4807b to your computer and use it in GitHub Desktop.
Save liushooter/1254a8d989b1b1f4807b to your computer and use it in GitHub Desktop.
/**
* 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, '&amp;').replace(/(<|>)/g, function(m){if('<' === m) return '&lt;'; else return '&gt;';});
/*
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