用百度編輯器——Ueditor(版本1.4.3.3,2016-05-18日上線)插入錨點的時候,每次總是失敗,百思不得其解。通過分析Ueditor的代碼ueditor.all.js,可以看出Ueditor插入錨點的過程,實際上是一個img標簽和a標簽相互轉換的過程,其代碼如下: 'anchor':{ ...
用百度編輯器——Ueditor(版本1.4.3.3,2016-05-18日上線)插入錨點的時候,每次總是失敗,百思不得其解。通過分析Ueditor的代碼ueditor.all.js,可以看出Ueditor插入錨點的過程,實際上是一個img標簽和a標簽相互轉換的過程,其代碼如下:
'anchor':{
//cmd:命令字元串,name:錨點名稱
execCommand:function (cmd, name) {
var range = this.selection.getRange(),img = range.getClosedNode();
if (img && img.getAttribute('anchorname')) {
if (name) {
img.setAttribute('anchorname', name);
} else {
range.setStartBefore(img).setCursor();
domUtils.remove(img);
}
} else {
if (name) {
//只在選區的開始插入
var anchor = this.document.createElement('img');
range.collapse(true);
domUtils.setAttributes(anchor,{
'anchorname':name,
'class':'anchorclass'
});
range.insertNode(anchor).setStartAfter(anchor).setCursor(false,true);
}
}
……
分析上述代碼,插入錨點的過程實際上在Ueditor中顯示的時候其實是插入了一個圖片(img元素),設置該img的anchorname屬性為插入錨點的名字。生成的HTML代碼形如”<img class='anchorclass' anchorname='title_01'>“其中“title_01”即為錨點的名字。代碼看起來是沒有問題的,筆者也多次使用alert調試,運行過程中是可以得到錨點的名稱‘name’的值的,但是在編輯器中查看源代碼的時候始終沒有anchorname屬性,於是筆者手動在得到的img標簽中寫入anchorname的屬性值,結果切換到顯示界面又切換回HTML界面後,該屬性依然丟失,真可謂百思不得其解。接著查看針對插入錨節點時的輸入規則(inputRule)和輸出規則(outputRule)部分的代碼,可以清晰的瞭解到輸出時Ueditor會將擁有anchorname屬性的img節點變成a(超級鏈接)節點,並將該img的anchorname屬性值作為'a'的name屬性值,這樣就完成了一個圖像錨像一個真正錨的變換,代碼如下:
outputRule: function(root){
utils.each(root.getNodesByTagName('img'),function(a){
var val;
if(val = a.getAttr('anchorname')){
a.tagName = 'a';
a.setAttr({
anchorname : '',
name : val,
'class' : ''
})
}
})
},
而輸入的時候使用的輸入規則(inputRule),是當用戶直接在其HTML源碼界面中輸入錨節點的代碼(比如:”<a name="title_01"></a>“)時,當用戶切換到顯示界面的時候,系統會自動將該錨點轉換成圖片錨,該圖片節點(img節點)的class="anchorclass",anchorname="title_01"(上述錨節點的name屬性值),代碼如下:
inputRule:function(root){
utils.each(root.getNodesByTagName('a'),function(a){
var val;
if((val = a.getAttr('name')) && !a.getAttr('href')){
a.tagName = 'img';
a.setAttr({
anchorname :a.getAttr('name'),
'class' : 'anchorclass'
});
a.setAttr('name')
}
})
},
這樣用戶看起來就有一個錨的圖片在剛纔插入錨的地方,而保存的時候仍然會使用outputRule,將該圖片變成一個真正的錨。
代碼的實現看起來一點問題也沒有,可是為什麼就是插入不了錨呢(實質上是在img節點中,無論如何也插入不了anchorname屬性,這點我在官網也嘗試過,也不行,可以說結結實實是個BUG)。
正當我以為該問題無解的時候,我突然發現原來在使用Ueditor的時候,除了引入了Ueditor.all.js外還引入了一個配置文件Ueditor.config.js,我覺得看看這個文件的代碼,這一下,終於被我找到了原因所在。原來在這個配置文件中定義了每個HTML標簽的過濾規則,也就是某個HTML標簽只能有哪些屬性,所以當我們加入其他屬性的時候是會被編輯器過濾掉的,比如我給img添加的achorename屬性(也就是上述程式在講錨轉換成圖片的時候要插入的屬性),因為在img的屬性過濾的白名單中是沒有該屬性的,所以照成了插入的失敗,也照成了編輯器插入錨節點時出現的BUG。同樣,筆者還發現在‘a’標簽的白名單中是沒有‘name’屬性的,也就是編輯器預設情況下是不能插入錨點的,將上述兩個屬性加入到配置文件中,問題得解,可以自由的插入任何錨節點了。下麵附上修改後的img和a標簽的白名單:
// xss 過濾是否開啟,inserthtml等操作
,xssFilterRules: true
//input xss過濾
,inputXssFilter: true
//output xss過濾
,outputXssFilter: true
// xss過濾白名單 名單來源: https://raw.githubusercontent.com/leizongmin
/js-xss/master/lib/default.js
,whitList: {
a: ['target', 'href', 'title', 'class', 'style','name'],
……
img: ['src', 'alt', 'title', 'width', 'height', 'id', '_src',
'loadingclass', 'class','anchorname']
當然還有其他的一些白名單,由於和本主題無關就不再一一羅列。以上就是我解決Ueditor插入錨點BUG的過程,也許您有更好的方法,請給我留言,謝謝!