富文本編輯器的基本原理與實(shí)踐
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
富文本編輯器,rich text editor, 簡(jiǎn)稱 rte, 它提供類似于 microsoft word 的編輯功能,容易被不會(huì)編寫 html 的用戶并需要設(shè)置各種文本格式的用戶所喜愛。它的應(yīng)用也越來(lái)越廣泛。最先只有 ie 瀏覽器支持,其它瀏覽器相繼跟進(jìn),在功能的豐富性來(lái)說(shuō),還是 ie 強(qiáng)些。雖然沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),但對(duì)于最基本的功能,各瀏覽器提供的 api 基本一致,從而使編寫一個(gè)跨瀏覽器的富文本編輯器成為可能。[br][br] 在很多開發(fā)者看來(lái),富文本編輯器的編寫是一件很神秘或者復(fù)雜的事情。神秘倒沒有,復(fù)雜的話,確實(shí)如此。但是它的基本原理并不復(fù)雜,入門也不難。今天我們的主題是講述基本原理,并逐步演示一個(gè)簡(jiǎn)單富文本編輯器的產(chǎn)生。這是我在 d2 上的一個(gè)分享內(nèi)容,在臺(tái)上的演講效果不佳,固寫下來(lái),希望能夠?qū)Ω信d趣的讀者有所幫助。[br][br] 富文本編輯器的基本原理[br][br] 這個(gè)原理實(shí)在是太簡(jiǎn)單了!對(duì)于支持富文本編輯的瀏覽器來(lái)說(shuō),其實(shí)就是設(shè)置 document 的 designmode 屬性為 on 后,再通過執(zhí)行 document.execcommand('commandname'[, uiflag[, value]]) 即可。commandname 和 value 可以在 msdn 上和mdc 上找到,它們就是我們創(chuàng)建各種格式的命令,比方說(shuō),我們要加粗字體,執(zhí)行 document.execcommand('bold', false) 即可。很簡(jiǎn)單是吧?但是值得注意的是,通常是選中了文本后才執(zhí)行命令,被選中的文本才被格式化。對(duì)于未選中的文本進(jìn)行這個(gè)命令,各瀏覽器有不同的處理方式,比方 ie 可能是對(duì)位于光標(biāo)中的標(biāo)簽內(nèi)容進(jìn)行格式化,而其它瀏覽器不做任何處理,這超出本文的內(nèi)容,不細(xì)述。同時(shí)需要注意的是,uiflag 這個(gè)參數(shù)設(shè)置為 true 表示 display any user interface triggered by the command (if any), 在我們今天的教程中都是 false, 而 value 也只在某些 commandname 中才有,具體參考以上剛給出的兩個(gè)鏈接。[br][br] 為了不影響當(dāng)前 document, 通常的做法是在頁(yè)面中嵌入一個(gè) iframe 元素,然后對(duì)這個(gè) iframe 內(nèi)的 document(通過 iframe.contentwindow.document 獲得)進(jìn)行操作。[br][br] 十分簡(jiǎn)單,是吧?下面我們來(lái)動(dòng)手做一個(gè)。[br][br] 編寫一個(gè)簡(jiǎn)單的富文本編輯器[br][br] 這個(gè)例子使用了 yui. 即使你對(duì)它不是很熟悉也沒有關(guān)系,我在這里只使用了它的 dom 和 event 的一些跨平臺(tái)基本方法。[br][br] 搭架[br][br] 在此強(qiáng)調(diào)一下很久未曾提及的 unobtrusive. 我們的編輯器是對(duì) textarea 元素的一個(gè)增強(qiáng)(enhencement),就是說(shuō),即使 javascript 被禁用了,用戶還可以通過 textarea 編輯內(nèi)容。[br][br] 在這個(gè)例子中,我們將使用 yahoo.realazy 的命名空間,在之下實(shí)現(xiàn)一個(gè) rte 的類。我們今天的編輯器很簡(jiǎn)單,因此構(gòu)造器(constructor) 的參數(shù)也只有 textarea 一個(gè)。我們使用一個(gè)實(shí)例變量來(lái)保存工具條的各個(gè)項(xiàng)目。實(shí)例初始化放到一個(gè)叫 render 的方法中。這一步的頁(yè)面和代碼見第 1 步。[br][br] 創(chuàng)建 iframe 并替換 textarea[br][br] 搭好架子,正如我在前面所說(shuō),建立一個(gè) iframe, 編輯器的所有操作都在 iframe 的 document 內(nèi)執(zhí)行。并且把 textarea 隱藏起來(lái)。從第 2 步中可以看到,我們已經(jīng)有了一個(gè) iframe, 但不能輸入任何東西,很正常,我們沒有打開它的 designmode 嘛。[br][br] 開啟 designmode[br][br] 這一步涉及的東西挺多,也是關(guān)鍵。我們會(huì)創(chuàng)建獲取 iframe 的 document 的方法,并通過程序的方式向 iframe 寫入空頁(yè)而非使用一個(gè)外接的 blank.html. 我們使用一個(gè)類屬性 yahoo.realazy.rte.htmlcontent 來(lái)保存空頁(yè)的 html. 在準(zhǔn)備好一切后,就可以開啟 designmode 了。頁(yè)面和代碼詳見第 3 步??矗覀円呀?jīng)可以在 iframe 里輸入東西了。[br][br] 構(gòu)建工具條[br][br] 我們需要操作的工具條!這樣才可以控制 iframe 里的內(nèi)容,才能稱之為編輯器。在此我并不打算實(shí)現(xiàn)太多的功能,只是選擇字形、字號(hào)、加粗、斜體、下劃線、居左、居中、居右、超鏈接和插圖作為示例。對(duì)于跨平臺(tái),mozilla midas specification 是不錯(cuò)的參考。ok, 請(qǐng)看第 4 步,我們的工具條出來(lái)了,雖然很丑。我同時(shí)用 css 對(duì) iframe 的寬度做出了一些調(diào)整。[br][br] 給工具條加上事件[br][br] 嗯,工具條出來(lái)了,編輯器看起來(lái)也“人模狗樣”了,你興奮的點(diǎn)啊點(diǎn),沒什么效果……意料中嘛。我們接著給工具條綁定一些事件,讓編輯器內(nèi)容能夠響應(yīng)工具條。在這一步,我們把 execcommand 再封一層,前面說(shuō)過,我們用不上 uiflag,讓它永遠(yuǎn)是 false 好了。好,有代碼就有真相,請(qǐng)看第 5 步。如果是正使用 ie, 請(qǐng)先暫時(shí)轉(zhuǎn)移到其它瀏覽器??吹搅税桑ぞ邨l生效了![br][br] 解決 ie 的問題[br][br] well, 如果你沒有聽我的勸告,依然使用 ie, 你會(huì)發(fā)現(xiàn)除了字型和字號(hào)其它的都不能用。為什么呢?你觀察一下,有沒有發(fā)現(xiàn),其它瀏覽器選擇文本后,再點(diǎn)擊工具條上的項(xiàng)目,被選中的文本是否依然選中的?而 ie 呢,在點(diǎn)擊工具條時(shí),選中的文本馬上失去選中的狀態(tài),所以它們就失敗了。所以,如果我們能夠保證點(diǎn)擊工具條文本保持選中狀態(tài),就可以解決 ie 的問題了。[br][br] microsoft 給 html 標(biāo)簽一個(gè)很奇怪的屬性 unselectable, 只要設(shè)置為 on, 焦點(diǎn)不會(huì)轉(zhuǎn)移到點(diǎn)擊的元素上,從而保證文本的選中狀態(tài)。[br][br] 請(qǐng)看第 6 步。這也是解決 ie 頭痛問題的關(guān)鍵所在。我曾經(jīng)在這上面費(fèi)了很大腦筋。[br][br] 高級(jí)主題展望[br][br] good, 看看我們現(xiàn)在的代碼,224 行。相比其它動(dòng)輒上萬(wàn)行的編輯器,你可能會(huì)覺得不可思議。因?yàn)槲覀冞@個(gè)最基本的編輯器,連 selection 都沒有用到。很多很酷的效果,比如 google doc 里能夠動(dòng)態(tài)改變鏈接文本,使用頁(yè)內(nèi)層而非彈出的 prompt 來(lái)操作等高級(jí)功能,基本上都要用到 textrange(ie) 或者 range(w3c). 要命的是這兩個(gè)東西互補(bǔ)兼容,只是相似而已。入門推薦看ppk 的 introduction to range.[br][br] 在此我們就不深入了,等我有時(shí)間我會(huì)總結(jié)一些奇技淫巧(嗚呼,前端開發(fā)需要的奇技淫巧太多了,這不是好事情)出來(lái)。
該文章在 2010/7/5 17:25:23 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |