自定義列表邏輯梳理

導(dǎo)語

在ckeditor中,列表是多層嵌套結(jié)構(gòu),li元素是ul或ol的唯一類型元素,所以被嵌套列表ul或ol必須被包在li下,由于層級的計(jì)算比較困難,所以改為單層嵌套。邏輯梳理如下:


列表有三種類型,分別為有序列表、無序列表以及選擇列表。其中有序列表與無序列表都封裝在UL標(biāo)簽中,而選擇列表由自定義標(biāo)簽CL來封裝。列表結(jié)構(gòu)為單層結(jié)構(gòu),即無嵌套DOM li節(jié)點(diǎn)。

有序列表

<ul>
  <li ce-para-type="ORDERED_LIST">
  ~
  </li>
</ul>

無序列表

<ul>
  <li ce-para-type="UNORDERED_LIST">
  ~
  </li>
</ul>

選擇列表

<ul>
  <li ce-para-type="CHECKED_LIST">
  ~
  </li>
</ul>

一.列表操作邏輯

代碼主要在list/plugin.js文件中,描述列表在操作時(shí)的功能展現(xiàn)。

添加列表

在文檔加載完成后,添加列表指的是由P段落轉(zhuǎn)變成各個(gè)列表的過程。
入口代碼:
createList.call( this, editor, groupObj, listsCreated );
在進(jìn)入入口之前,選取選擇區(qū)域的節(jié)點(diǎn)數(shù)組(groupObj.contents),依次處理數(shù)組中的內(nèi)容,變?yōu)橹付斜?。最后重新?jì)算序號標(biāo)簽。

變換列表

列表三種樣式互換的過程。
入口代碼:
changeListType.call( this, editor, groupObj, database, listsCreated );
通過listArray方法將實(shí)際列表節(jié)點(diǎn)包裝成指定數(shù)組,操作數(shù)組,將每個(gè)元素替換標(biāo)簽。同時(shí)將元素所在的列表群同時(shí)變換樣式。其中選擇列表變?yōu)橛行蚧驘o序列表時(shí),會(huì)消除最外層的刪除線(局部刪除線保留)。

刪除列表

入口代碼:
removeList.call( this, editor, groupObj, database );
刪除列表指的是由各個(gè)列表轉(zhuǎn)變成P段落的過程。
將選中的列表(列表組)的屬性和子節(jié)點(diǎn)全部放在新建的普通段落中,若普通段落里面沒有內(nèi)容,用br填充,其后的節(jié)點(diǎn)序號重算,并放入一個(gè)新建的與原父節(jié)點(diǎn)相同的標(biāo)簽中。插入在新建的普通段落之后。

列表層級變換

樣式全部由CSS來控制,層級變換是通過修改節(jié)點(diǎn)屬性來實(shí)現(xiàn)。共8級層級。

///script/ckeditor/plugins/indentlist/plugin.js
function indent( listNode ) {
···
var indentOffset = that.isIndent ? 1 : -1;
listArray[k].indent += indentOffset;
···
}

層級變換需要確定選中的都是列表,在代碼中在這方面寫了保護(hù)機(jī)制。在CL中input框需要重寫響應(yīng)事件。每次縮進(jìn)操作都會(huì)重算序號。

二.列表同步與加載邏輯

代碼主要在coedit/plugin.js文件中,描述列表加載與同步的功能展現(xiàn)。
有序列表和無序列表加載與更新是一組函數(shù),選擇列表加載和更新是另外一組函數(shù)。

列表查找

編輯框中根據(jù)ID全查找,入特定數(shù)組。
數(shù)組格式
[列表類型,列表縮進(jìn)值,列表本身節(jié)點(diǎn)]
無法找到節(jié)點(diǎn)
[-1,undefined,undefined]

列表加載

依賴段落ID(string)與插入位置(bool)

有序列表和無序列表插入

判斷基本段落類型,分情況插入

//找到段落
if(basePara[1] >= 0 && basePara[0] != 3)//有序列表和無序列表
}else if(basePara[0] == 3){//選擇列表
else{//普通段落
}
//找不到段落
//插入首個(gè)帶有ID段落的前面
newNodePack.insertBefore( baseElement );

插入段落后進(jìn)行段落序號重排

有序列表和無序列表更新

判斷被更新段落類型,分情況更新

if(baseType == 'other'){
//普通段落轉(zhuǎn)列表
}else if(newNodeTag == 'other'){
//列表轉(zhuǎn)普通段落
}else{
//列表更新為列表
oNewElement.insertAfter(basePara[2]);
}

列表更新完成后,查看被更新段落的父節(jié)點(diǎn)(ul)是否將會(huì)出現(xiàn)沒有子元素的情況,若將會(huì)出現(xiàn),則刪除父節(jié)點(diǎn);若不出現(xiàn),重新計(jì)算,上下段落合并。

選擇列表的插入

對選擇列表的上下環(huán)境進(jìn)行判斷,對列表節(jié)點(diǎn)進(jìn)行包裹

switch(basePara[0]){
case 0:
  readyToInsert = newNodePack;
break;
case 1:
case 2:
  var listLevel = basePara[1];
  readyToInsert = newNodePack;
  baseElement = baseElement.getParent();
  break;
case 3:
  break;
default:
  break;
}

包裹后前后插入,若找不到段落,處理情況和普通列表無法找到段落的情況一致。

選擇列表的更新

只有被更新項(xiàng)為選擇列表或者將要更新為選擇列表,回進(jìn)入此函數(shù)執(zhí)行

if(basePara[0] == 3){
  if(newNodeTag == 'cl'){
  //check變check
  }else if(newNodeTag != 'other'){
  //check變列表,basePara中的所有節(jié)點(diǎn)都要變
  }else{
  //check變普通段落
  }
}else if(newNodeTag == 'cl'){
  if(basePara[0] == 0){
  //普通段落變check
  }else if(basePara[0] == 1 || basePara[0] == 2){
  //列表變check,增加小框
  }
}

變成普通段落:原段落序號重算
變成選擇列表:對Input事件添加
變?yōu)槠渌斜恚盒蛱栔厮悖舷露温浜喜?br> 若找不到段落,控制臺(tái)出現(xiàn)警告提醒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容