昨晚fix了本博客一个剪贴复制的问题。

需求:希望在编辑博客时能够直接剪贴复制图片到文本框中,这样可以简单快捷的编写文章。

解决方法:是通过javascript来允许用户来粘贴图片到一个div中,然后再复制到文本框中。在读取event.clipboardData的时候chrome和Firefox出现了不同的行为。原因是firefox在某个版本后并不允许javascript访问剪贴板。

安全问题:

允许浏览器访问剪贴板有一定安全问题,正常浏览器可以设置。IE设置如下:

下面是综合网上的解决办法的一个实现:

HTML:

<div id='div' contenteditable='true' onpaste='handlepaste(this, event)'>Paste</div>

Javascript:

function handlepaste (elem, e) {
    var savedcontent = elem.innerHTML;
    if (e && e.clipboardData && e.clipboardData.getData) {// Webkit - get data from clipboard, put into editdiv, cleanup, then cancel event
        if (/text\/html/.test(e.clipboardData.types)) {
            elem.innerHTML = e.clipboardData.getData('text/html');
        }
        else if (/text\/plain/.test(e.clipboardData.types)) {
            elem.innerHTML = e.clipboardData.getData('text/plain');
        }
        else {
            elem.innerHTML = "";
        }
        waitforpastedata(elem, savedcontent);
        if (e.preventDefault) {
                e.stopPropagation();
                e.preventDefault();
        }
        return false;
    }
    else {// Everything else - empty editdiv and allow browser to paste content into it, then cleanup
        elem.innerHTML = "";
        waitforpastedata(elem, savedcontent);
        return true;
    }
}

function waitforpastedata (elem, savedcontent) {
    if (elem.childNodes && elem.childNodes.length > 0) {
        processpaste(elem, savedcontent);
    }
    else {
        that = {
            e: elem,
            s: savedcontent
        }
        that.callself = function () {
            waitforpastedata(that.e, that.s)
        }
        setTimeout(that.callself,20);
    }
}

function processpaste (elem, savedcontent) {
    pasteddata = elem.innerHTML;
    //^^Alternatively loop through dom (elem.childNodes or elem.getElementsByTagName) here

    elem.innerHTML = savedcontent;

    // Do whatever with gathered data;
    alert(pasteddata);
}

处理粘贴的过程大体如下:

function handlepaste (elem, e) {
	/****
	*0.先保存原先Element内容以备后用;
	*1.粘贴板上获取数据
	*2.放到editDiv
	*3.清除数据
	*4.结束事件
	**/	
	
	//先保存原先Element内容以备后用;
    var savedcontent = elem.innerHTML;
	如果是 (支持e.clipboardData的Webkit类型的浏览器:chrome or safari) 则{
		根据e.clipboardData.types来判断数据源类型,从而根据相应的类型处理数据。
		数据可以通过e.clipboardData.getData来获取。
		本例中只针对text/html 或text/plain的数据源做了处理,其他都设为空。
		 if (/text\/html/.test(e.clipboardData.types)) {
            elem.innerHTML = e.clipboardData.getData('text/html');
        }else if (/text\/plain/.test(e.clipboardData.types)) {
            elem.innerHTML = e.clipboardData.getData('text/plain');
        }else {
            elem.innerHTML = "";
        }
        waitforpastedata(elem, savedcontent);
		然后结束事件。
		if (e.preventDefault) {
                e.stopPropagation();
                e.preventDefault();
        }
	} 否则 就{
		//这类浏览器允许用户直接贴内容到里面(包括图片内容),但是需要时间等待处理。
		elem.innerHTML = "";
        waitforpastedata(elem, savedcontent);
	}
}

//需要等待粘贴的过程,因为它整个过程不是一瞬间的事,有可能花些时间,取决于粘贴内容的大小。
function waitforpastedata (elem, savedcontent) {
    if (elem.childNodes && elem.childNodes.length > 0) {
	//粘贴已结束,可以处理数据。
        processpaste(elem, savedcontent);
    }else {
	//粘贴还未结束,需要继续等待。
        that = {
            e: elem,
            s: savedcontent
        }
        that.callself = function () {
            waitforpastedata(that.e, that.s)
        }
        setTimeout(that.callself,20);
    }
}

function processpaste (elem, savedcontent) {
    //简单获取粘贴内容并alert,值设为原始内容
    pasteddata = elem.innerHTML;
    elem.innerHTML = savedcontent;
    // Do whatever with gathered data;
    alert(pasteddata);
}

这边贴一个复制粘贴图片的例子,需要稍作修改:

// We start by checking if the browser supports the 
	// Clipboard object. If not, we need to create a 
	// contenteditable element that catches all pasted data 
	if (!window.Clipboard) {
	   var pasteCatcher = document.createElement("div");
	    
	   // Firefox allows images to be pasted into contenteditable elements
	   pasteCatcher.setAttribute("contenteditable", "");
	    
	   // We can hide the element and append it to the body,
	   pasteCatcher.style.opacity = 0;
	   document.body.appendChild(pasteCatcher);
	 
	   // as long as we make sure it is always in focus
	   pasteCatcher.focus();
	   document.addEventListener("click", function() { pasteCatcher.focus(); });
	} 
	// Add the paste event listener
	window.addEventListener("paste", pasteHandler);
	 
	/* Handle paste events */
	function pasteHandler(e) {
	   // We need to check if event.clipboardData is supported (Chrome)
	   if (e.clipboardData) {
	      // Get the items from the clipboard
	      var items = e.clipboardData.items;
	      if (items) {
	         // Loop through all items, looking for any kind of image
	         for (var i = 0; i < items.length; i++) {
	            if (items[i].type.indexOf("image") !== -1) {
	               	// We need to represent the image as a file,
	               	var blob = items[i].getAsFile();          	               	            
					var reader = new FileReader();
					reader.onload = function(event){
						createImage(event.target.result); 
					};
					reader.readAsDataURL(blob);
	            }
	         }
	      }
	   // If we can't handle clipboard data directly (Firefox), 
	   // we need to read what was pasted from the contenteditable element
	   } else {
	      // This is a cheap trick to make sure we read the data
	      // AFTER it has been inserted.
	      setTimeout(checkInput, 1);
	   }
	}
	 
	/* Parse the input in the paste catcher element */
	function checkInput() {
	   // Store the pasted content in a variable
	   var child = pasteCatcher.childNodes[0];
	 
	   // Clear the inner html to make sure we're always
	   // getting the latest inserted content
	   pasteCatcher.innerHTML = "";
	    
	   if (child) {
	      // If the user pastes an image, the src attribute
	      // will represent the image as a base64 encoded string.
	      if (child.tagName === "IMG") {
	         createImage(child.src);
	      }
	   }
	}
	 
	/* Creates a new image from a given source */
	function createImage(source) {
	   var pastedImage = new Image();
	   pastedImage.onload = function() {
	      // You now have the image!
	   }
	   pastedImage.src = source;
	   pastedImage.id='screenShot';
	   pastedImage.className='screenShot';
	   $('#pasteImg').empty().append(pastedImage);
	}

发表评论