麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > 綜合 > 正文

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數據將在下一篇講解。


注:相關教程知識閱讀請移步到編輯器頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: h视频在线观看免费 | 欧美成人国产va精品日本一级 | 成人毛片100部 | 中国性xxx | 27xxoo无遮挡动态视频 | 91成人在线免费观看 | 九九视屏 | 日本欧美一区二区三区视频麻豆 | 免费观看视频在线观看 | 久久宗合色 | 日产精品久久久一区二区开放时间 | 国产成人综合在线观看 | 欧美毛片免费观看 | 精品国产一区二区三区久久久狼牙 | 成人福利免费在线观看 | 亚洲午夜网站 | 污视频在线免费播放 | 中文字幕在线成人 | 羞羞视频免费观看入口 | 污黄视频在线观看 | 最新中文字幕在线 | 在线播放免费人成毛片乱码 | 免费h片网站 | 欧美视屏一区二区 | 精品亚洲免费 | 国产午夜精品一区 | 久久久久久久久久久一区 | 黄色一级视频 | 玩偶姐姐 在线观看 | 国产精品99一区二区 | 欧美激情图区 | 国产成人在线网站 | 国产成人高清在线观看 | 91精品视频网址 | 中文欧美日韩 | 日本在线播放一区二区三区 | 91精品视频免费 | 精品国产一区三区| 午夜视频你懂的 | 国内精品伊人久久久久网站 | 在线免费小视频 |