亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Html編輯器粘貼內容過濾技術詳解

2024-07-21 02:53:46
字體:
來源:轉載
供稿:網友
最近在解決數據粘貼方面取得了不少進展,作為Html在線編輯器所必須具備的技術,在這里詳細給大家介紹并提供實現參考。
 
作者:Tony Qu 
最近在解決數據粘貼方面取得了不少進展,作為Html在線編輯器所必須具備的技術,在這里詳細給大家介紹并提供實現參考。在研究過程中,我也確實走了不少彎路,嘗試了n種方式,由于美國的PM始終覺得有些影響用戶體驗的東西無法接受,導致好幾個提案被否定,不過收獲還是很豐富的。 
我現在寫code喜歡需求驅動,讓我們來看看這項技術的主要需求 
* 能夠過濾用戶貼進來的純文本數據 
* 能夠過濾用戶貼進來的html數據(未經Html編碼) 
* 能夠過濾用戶貼進來的Word數據,并能把大部分Word格式保留下來。 
* 在這一過程中盡量不要讓用戶知道我們在做過濾 
* 不要去提示用戶是否啟用某種權限 
本例所適用的場景為使用iframe實現的Html編輯器,而不是文本框(textarea或type為text的input)。 

在研究過程中,我主要參考了tinymce、ckeditor,但最后我還是選擇了tinymce的實現方法,具體原因在你看完下面這段文字后就會明白。 
ckeditor的實現方式是在onpaste事件觸發時,從剪貼板取出數據,處理取出的文本,然后再把處理好的文本存入剪貼板。有人說,那我能不能在onpaste中直接取消paste動作,然后自己把獲得的內容放入iframe當中去,我當時就干過這事,但結果卻出人意料,直接從剪貼板拿出的數據是不包括格式信息的文本,特別是從Word粘貼過來的數據,純文本,顏色、布局等數據都不存在,這樣的話,你的用戶只能粘貼沒有格式的數據過來,然后自己重新在Html編輯器里面編輯。但是如果讓瀏覽器自己去做粘貼,格式信息都會保留,瀏覽器會自動把Word的粘貼數據轉換為xml數據,放入dom中。所以為了保留格式信息,我們恐怕只能通過瀏覽器的標準粘貼行為的幫助實現這一點。 
另外ckeditor的實現在Firefox中有一個致命的弱點,如果你要從剪貼板讀寫數據,你就必須提示用戶自己去設置一個叫signed.applets.codebase_principal_support的權限,javascript腳本是沒有權限去設置的,雖然從技術人員來看這是很正常的,但是很多產品經理無法接受這一點,至少我的產品經理是這么認為的。 
以下是ckeditor獲取和設置剪貼板的代碼,供大家參考。 
復制代碼代碼如下:

function setClipboard(maintext) { 
if (window.clipboardData) { 
return (window.clipboardData.setData("Text", maintext)); 

else if (window.netscape) { 
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); 
var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard); 
if (!clip) return; 
var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable); 
if (!trans) return; 
trans.addDataFlavor('text/unicode'); 
var str = new Object(); 
var len = new Object(); 
var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString); 
var copytext=maintext; 
str.data=copytext; 
trans.setTransferData("text/unicode",str,copytext.length*2); 
var clipid=Components.interfaces.nsIClipboard; 
if (!clip) return false; 
clip.setData(trans,null,clipid.kGlobalClipboard); 
return true; 

return false; 

function getClipboard() { 
if (window.clipboardData) { 
return(window.clipboardData.getData('Text')); 

else if (window.netscape) { 
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); 
var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard); 
if (!clip) return; 
var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable); 
if (!trans) return; 
trans.addDataFlavor('text/unicode'); 
clip.getData(trans,clip.kGlobalClipboard); 
var str = new Object(); 
var len = new Object(); 
try { 
trans.getTransferData('text/unicode',str,len); 

catch(error) { 
return null; 

if (str) { 
if (Components.interfaces.nsISupportsWString) str=str.value.QueryInterface(Components.interfaces.nsISupportsWString); 
else if (Components.interfaces.nsISupportsString) str=str.value.QueryInterface(Components.interfaces.nsISupportsString); 
else str = null; 

if (str) { 
return(str.data.substring(0,len.value / 2)); 


return null; 

以下是提示用戶啟用權限的代碼 
復制代碼代碼如下:

if (window.netscape) 

try 

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); 

catch (ex) 

alert("If you want to do paste, please input 'about:config' in address bar, then input Enter./n Set /"signed.applets.codebase_principal_support/" to /"true/""); 


于是我參考了tinymce的實現方式,我在看它的代碼的時候特別留意到它盡然不需要權限就能在Firefox下面搞定粘貼,并且還能保留Word格式,于是就仔細閱讀了其中的代碼。tinymce的實現步驟在IE和Firefox下面是不同的: 
IE實現 
1. 在onpaste回調函數中創建一個臨時的iframe,用于粘貼內容,這個iframe放在主窗口的body下面即可。 
2. 在當前光標位置創建一個Range,用來保存光標位置和選中信息。 
3. 讓臨時iframe獲得焦點,執行粘貼命令,即document.execCommand(“paste”),內容會粘貼在臨時的iframe中 
4. 通過innerHTML獲得臨時iframe中的內容并進行過濾 
5. 讓Html編輯器的iframe獲得焦點,用之前創建的Range對象執行pasteHTML方法來粘貼過濾后的內容 
6. 最后取消默認的paste動作 
(臨時iframe可以根據個人喜好從DOM中刪除,但由于這個iframe可以在多個htmleditor之間共用,所以我的實現中僅僅改變了iframe的left, top來調整iframe的位置,而不是移除它,調整left和top的目的在于焦點移到臨時iframe的時候如果Html編輯器的iframe和臨時iframe不在一個視圖之內,屏幕會滾動,這樣會導致屏幕沒有原因的閃爍。) 
Firefox實現 
1. 在onpaste回調函數中創建一個臨時的div,這個div放在Html編輯器的iframe里面,這也是繞過權限問題的關鍵。 
2. 保存當前光標和焦點位置,然后將光標移到臨時創建的div中 
3. 通過window.setTimeout設置一個回調函數在paste動作瞬間完成之后執行 
4. 讓paste動作執行(onpaste回調函數執行完畢) 
5. 剛才設置的回調函數執行,在里面獲得臨時div的innerHTML并進行過濾 
6. 恢復剛才保存的光標和焦點位置,并移除臨時div 
7. 通過inserthtml命令(execCommand(“inserthtml”))把過濾后的內容貼到Html編輯器的iframe中。 

詳細代碼如下: 
復制代碼代碼如下:

function getSel(w) 

return w.getSelection ? w.getSelection() : w.document.selection; 

function setRange(sel,r) 

sel.removeAllRanges(); 
sel.addRange(r); 

function filterPasteData(originalText) 

var newText=originalText; 
//do something to filter unnecessary data 
return newText; 

function block(e) 

e.preventDefault(); 

var w,or,divTemp,originText; 
var newData; 
function pasteClipboardData(editorId,e) 

var objEditor = document.getElementById(editorId); 
var edDoc=objEditor.contentWindow.document; 
if(isIE) 

var orRange=objEditor.contentWindow.document.selection.createRange(); 
var ifmTemp=document.getElementById("ifmTemp"); 
if(!ifmTemp) 

ifmTemp=document.createElement("IFRAME"); 
ifmTemp.id="ifmTemp"; 
ifmTemp.style.width="1px"; 
ifmTemp.style.height="1px"; 
ifmTemp.style.position="absolute"; 
ifmTemp.style.border="none"; 
ifmTemp.style.left="-10000px"; 
ifmTemp.src="iframeblankpage.html"; 
document.body.appendChild(ifmTemp); 
ifmTemp.contentWindow.document.designMode = "On"; 
ifmTemp.contentWindow.document.open(); 
ifmTemp.contentWindow.document.write("<body></body>"); 
ifmTemp.contentWindow.document.close(); 
}else 

ifmTemp.contentWindow.document.body.innerHTML=""; 

originText=objEditor.contentWindow.document.body.innerText; 
ifmTemp.contentWindow.focus(); 
ifmTemp.contentWindow.document.execCommand("Paste",false,null); 
objEditor.contentWindow.focus(); 
newData=ifmTemp.contentWindow.document.body.innerHTML; 
//filter the pasted data 
newData=filterPasteData(newData); 
ifmTemp.contentWindow.document.body.innerHTML=newData; 
//paste the data into the editor 
orRange.pasteHTML(newData); 
//block default paste 
if(e) 

e.returnValue = false; 
if(e.preventDefault) 
e.preventDefault(); 

return false; 
}else 

enableKeyDown=false; 
//create the temporary html editor 
var divTemp=edDoc.createElement("DIV"); 
divTemp.id='htmleditor_tempdiv'; 
divTemp.innerHTML='/uFEFF'; 
divTemp.style.left="-10000px"; //hide the div 
divTemp.style.height="1px"; 
divTemp.style.width="1px"; 
divTemp.style.position="absolute"; 
divTemp.style.overflow="hidden"; 
edDoc.body.appendChild(divTemp); 
//disable keyup,keypress, mousedown and keydown 
objEditor.contentWindow.document.addEventListener("mousedown",block,false); 
objEditor.contentWindow.document.addEventListener("keydown",block,false); 
enableKeyDown=false; 
//get current selection; 
w=objEditor.contentWindow; 
or=getSel(w).getRangeAt(0); 
//move the cursor to into the div 
var docBody=divTemp.firstChild; 
rng = edDoc.createRange(); 
rng.setStart(docBody, 0); 
rng.setEnd(docBody, 1); 
setRange(getSel(w),rng); 
originText=objEditor.contentWindow.document.body.textContent; 
if(originText==='/uFEFF') 

originText=""; 

window.setTimeout(function() 

//get and filter the data after onpaste is done 
if(divTemp.innerHTML==='/uFEFF') 

newData=""; 
edDoc.body.removeChild(divTemp); 
return; 

newData=divTemp.innerHTML; 
// Restore the old selection 
if (or) 

setRange(getSel(w),or); 

newData=filterPasteData(newData); 
divTemp.innerHTML=newData; 
//paste the new data to the editor 
objEditor.contentWindow.document.execCommand('inserthtml', false, newData ); 
edDoc.body.removeChild(divTemp); 
},0); 
//enable keydown,keyup,keypress, mousedown; 
enableKeyDown=true; 
objEditor.contentWindow.document.removeEventListener("mousedown",block,false); 
objEditor.contentWindow.document.removeEventListener("keydown",block,false); 
return true; 


這里的pasteClipboardData是用做onpaste回調函數的,要使用它的話,可以通過下面的代碼把它加到Html編輯器的iframe的onpaste事件上。 
復制代碼代碼如下:

var ifrm=document.getElementById("editor") 
if(isIE) 

ifrm.contentWindow.document.documentElement.attachEvent("onpaste", function(e){return pasteClipboardData(ifrm.id,e);}); 

else 

ifrm.contentWindow.document.addEventListener("paste", function(e){return pasteClipboardData(ifrm.id,e);},false); 

這里的filterPasteData函數就是我們專門用來做過濾的函數,具體要怎么去過濾純文本、html及Word數據將在下一篇講解。


注:相關教程知識閱讀請移步到編輯器頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
免费不卡欧美自拍视频| 中文国产成人精品久久一| 美女国内精品自产拍在线播放| 国产精品久久久久国产a级| 免费av在线一区| 久久久精品视频成人| 美女久久久久久久久久久| 啊v视频在线一区二区三区| 欧美性资源免费| 中文字幕在线成人| 欧美床上激情在线观看| 久久久91精品国产一区不卡| 亚洲成**性毛茸茸| 国产精品免费在线免费| 亚洲影影院av| 亚洲一二在线观看| 亚洲一区二区三区在线免费观看| 91精品啪aⅴ在线观看国产| 欧美精品久久一区二区| 欧美裸体xxxx极品少妇软件| 欧美夜福利tv在线| 黄色成人av网| 蜜臀久久99精品久久久无需会员| 国产免费亚洲高清| 久热精品视频在线观看一区| 亚洲欧美成人精品| 亚洲天堂av在线播放| 亚洲乱码一区二区| 久久av中文字幕| 欧美日韩xxx| 国产欧美va欧美va香蕉在线| 日韩av中文在线| 91亚洲精品在线观看| 黑人欧美xxxx| 国产成人精品免费久久久久| 日韩电影中文字幕在线| 亚洲无亚洲人成网站77777| 久久天天躁狠狠躁夜夜爽蜜月| 久久精品成人欧美大片古装| 韩国19禁主播vip福利视频| 最新国产成人av网站网址麻豆| 日本人成精品视频在线| 亚洲伊人久久综合| 国产91热爆ts人妖在线| 色噜噜狠狠狠综合曰曰曰| 亚洲午夜国产成人av电影男同| 国产精品自拍网| 欧美性猛交xxxx久久久| 欧美一级大片视频| 26uuu久久噜噜噜噜| 久久99热这里只有精品国产| 中国china体内裑精亚洲片| 久久综合88中文色鬼| 亚洲国产精品va在线观看黑人| 色诱女教师一区二区三区| 日韩av在线网页| 国产精品福利在线| 久久中国妇女中文字幕| 国产成人啪精品视频免费网| 欧美一级大胆视频| 91人人爽人人爽人人精88v| 久久久久久香蕉网| 欧美大片在线影院| 欧美视频不卡中文| 疯狂蹂躏欧美一区二区精品| 国产日产欧美精品| 91久久久久久国产精品| 日韩风俗一区 二区| 精品夜色国产国偷在线| 亚洲综合成人婷婷小说| 久久天天躁夜夜躁狠狠躁2022| 青青在线视频一区二区三区| 4k岛国日韩精品**专区| 日韩av中文字幕在线| 欧美激情国产精品| 久久夜精品va视频免费观看| 亚洲欧美中文日韩在线| 午夜欧美大片免费观看| 亚洲国产女人aaa毛片在线| 欧洲中文字幕国产精品| 另类少妇人与禽zozz0性伦| 精品成人国产在线观看男人呻吟| 26uuu亚洲国产精品| 在线成人激情黄色| 欧美在线国产精品| 国产成人在线一区| 久久网福利资源网站| 欧美日韩亚洲系列| 亚洲精品国产综合久久| 国产精品第一页在线| 欧美午夜激情小视频| 成人伊人精品色xxxx视频| 亚洲成人精品av| 高清欧美性猛交| 亚洲欧洲日产国码av系列天堂| 97热精品视频官网| 欧美日韩综合视频网址| 日韩经典第一页| 亚洲欧美自拍一区| 欧美黑人国产人伦爽爽爽| 欧美第一黄色网| 久久婷婷国产麻豆91天堂| 精品国产乱码久久久久久天美| 久久免费国产精品1| 一区二区三区视频免费在线观看| 亚洲成人久久网| 久久久天堂国产精品女人| 中文字幕亚洲一区在线观看| 欧美另类交人妖| 国产精品久久久久久久久久久久久久| 欧美激情一区二区三区高清视频| 在线电影av不卡网址| 国产亚洲欧洲在线| 91麻豆国产语对白在线观看| 亚洲欧美激情四射在线日| 国产一区香蕉久久| 亚洲欧美国产一区二区三区| 成人黄色av网站| 日韩中文字幕网址| 中文字幕欧美日韩精品| 超薄丝袜一区二区| 亚洲aaa激情| 人人做人人澡人人爽欧美| 国语自产精品视频在线看一大j8| 欧美久久久精品| 国产精品久久中文| 欧洲成人免费aa| 色综合老司机第九色激情| 热草久综合在线| 国产精品美女无圣光视频| 亚洲成人av片在线观看| 亚洲国产毛片完整版| 久久久久久久久久久免费精品| 色悠悠久久88| 国语对白做受69| 亚洲高清久久久久久| 国产精品久久久久久久久久久不卡| 亚洲国产精品久久久久久| 亚洲黄色成人网| 色婷婷av一区二区三区在线观看| 超在线视频97| 亚洲成人黄色网址| 成人免费网站在线看| 中文字幕亚洲欧美在线| 国产在线观看一区二区三区| 亚洲欧美在线第一页| 日韩在线高清视频| 国语自产精品视频在线看| 91超碰caoporn97人人| 日韩欧美国产视频| 久久久97精品| 欧美国产在线视频| 日韩精品在线视频美女| 日韩免费观看视频| 欧美色xxxx| 成人免费xxxxx在线观看| 91免费看国产| 日韩精品在线播放| 都市激情亚洲色图| 在线亚洲欧美视频| 亚洲午夜小视频| 91免费精品视频| 国产精品久久不能| 国产精品永久免费在线|