FCKeditor 將BBCODE 應用於FCKeditor內
- 2009-09-05
- 11261
- 0
demo 之前介紹 FCKeditor 的篇幅也不少,也因為他太好用了,demo也是一直都使用他作為線上編輯器,最近客戶有個需求要高度資安但卻又要讓使用者改變字型顏色或設定超連結,當然還是使用 FCKeditor 來達成啦,現在就來紀錄一下。
好在之前的映像中 FCKeditor 就可以支援 BBCODE 查了一下果然是沒錯,再來就設定開始啦。
必須下載官方的完整檔,如果你下載的是精簡版就沒有該功能。
首先我們至FCK的資料夾找到設定檔 fckconfig.js 找到大約53行的部份增加以下的code
FCKConfig.PluginsPath = FCKConfig.BasePath + 'plugins/' ; FCKConfig.Plugins.Add( 'bbcode' ) ;//加的是這行 // FCKConfig.Plugins.Add( 'autogrow' ) ; // FCKConfig.Plugins.Add( 'dragresizetable' ); FCKConfig.AutoGrowMax = 400 ;
這樣就可以改成使用BBOCDE了


但是預設的轉換標籤相當的少只有 「B」「I」「U」「URL」看得出來夠用才有鬼...因此我們需要修改一下,前進至以下路徑
網站\fck\editor\plugins\bbcode\fckplugin.js
將此檔案打開貼上以下的CODE
/*
* FCKeditor - The text editor for Internet - http://www.fckeditor.net
* Copyright (C) 2003-2009 Frederico Caldeira Knabben
*
* == BEGIN LICENSE ==
*
* Licensed under the terms of any of the following licenses at your
* choice:
*
* - GNU General Public License Version 2 or later (the "GPL")
* http://www.gnu.org/licenses/gpl.html
*
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
* http://www.gnu.org/licenses/lgpl.html
*
* - Mozilla Public License Version 1.1 or later (the "MPL")
* http://www.mozilla.org/MPL/MPL-1.1.html
*
* == END LICENSE ==
*
* This is a sample implementation for a custom Data Processor for basic BBCode.
*/
FCK.DataProcessor =
{
/*
* Returns a string representing the HTML format of "data". The returned
* value will be loaded in the editor.
* The HTML must be from <html> to </html>, eventually including
* the DOCTYPE.
* @param {String} a to be converted in the
* DataProcessor sdata The datpecific format.
*/
ConvertToHtml: function(data) {
// Convert < and > to their HTML entities.
data = data.replace(/</g, '<');
data = data.replace(/>/g, '>');
// Convert line breaks to <br>.
data = data.replace(/(?:\r\n|\n|\r)/g, '<br>');
// [url]
data = data.replace(/\[URL\]([\s\S]*?)\[\/URL\]/gim, '<a href="$1">$1</a>');
data = data.replace(/\[URL\=([^\]]+)]([\s\S]*?)\[\/URL\]/gim, '<a href="$1">$2</a>');
// [b]
data = data.replace(/\[B\]([\s\S]*?)\[\/B\]/gim, '<b>$1</b>');
// [i]
data = data.replace(/\[I\]([\s\S]*?)\[\/I\]/gim, '<i>$1</i>');
// [u]
data = data.replace(/\[U\]([\s\S]*?)\[\/U\]/gim, '<u>$1</u>');
// [IMG]
data = data.replace(/\[IMG\=["']([^\]]+)["']\]/gim, '<img src="$1">');
// [FONT]
data = data.replace(/\[FONT\=["']([^\]]+)["']\]([\s\S]*?)\[\/FONT\]/gim, '<span style="font-family: $1;">$2</span>');
// [SIZE]
data = data.replace(/\[SIZE\=["']([^\]]+)["']\]([\s\S]*?)\[\/SIZE\]/gim, '<span style="font-size: $1;">$2</span>');
// [COLOR]
data = data.replace(/\[COLOR\=["']([^\]]+)["']\]([\s\S]*?)\[\/COLOR\]/gim, '<span style="color: $1;">$2</span>');
// [CENTER]
data = data.replace(/\[CENTER\]([\s\S]*?)\[\/CENTER\]/gim, '<span style="text-align:center;">$2</span>');
// [LEFT]
data = data.replace(/\[LEFT\]([\s\S]*?)\[\/LEFT\]/gim, '<span style="text-align:left;">$2</span>');
// [RIGHT]
data = data.replace(/\[RIGHT\]([\s\S]*?)\[\/RIGHT\]/gim, '<span style="text-align:right;">$2</span>');
//[BLOCK]
data = data.replace(/\[BLOCK\]([\s\S]*?)\[\/BLOCK\]/gim, '<blockquote>$1</blockquote>');
//LI - goes before parents replacement [OL] or [UL]
data = data.replace(/\[\*\]([\s\S]*?)\[\*\]/gim, '<li>$1</li>');
data = data.replace(/\[\*\]([\s\S]*?)\[\/LIST\]/gim, '<li>$1</li>');
// Ordered List [OL]
data = data.replace(/\[LIST\=1\]([\s\S]*?)\[\/LIST\]/gim, '<ol>$1</ol>');
// Unordered List [UL]
data = data.replace(/\[LIST\]([\s\S]*?)\[\/LIST\]/gim, '<ul>$1</ul>');
// [spoiler]
data = data.replace(/\[SPOILER\]([\s\S]*?)\[\/SPOILER\]/gim, '<span style="background-color:#666666;color:#666666;">$1</span>');
// [INDENT]
data = data.replace(/\[INDENT\=["']([^\]]+)["']\]([\s\S]*?)\[\/INDENT\]/gim, '<div style="margin-left: $1;">$2</div>');
return '<html><head><title></title></head><body>' + data + '</body></html>';
},
/*
* Converts a DOM (sub-)tree to a string in the data format.
* @param {Object} rootNode The node that contains the DOM tree to be
* converted to the data format.
* @param {Boolean} excludeRoot Indicates that the root node must not
* be included in the conversion, only its children.
* @param {Boolean} format Indicates that the data must be formatted
* for human reading. Not all Data Processors may provide it.
*/
ConvertToDataFormat: function(rootNode, excludeRoot, ignoreIfEmptyParagraph, format) {
var data = rootNode.innerHTML;
// Convert <br> to line breaks.
data = data.replace(/<br(?=[ \/>]).*?>/gim, '\r\n');
// [URL]
data = data.replace(/<a .*?href=(["'])(.+?)\1.*?>(.+?)<\/a>/gi, '[url=$2]$3[/url]');
// [B]
data = data.replace(/<(?:b|strong)>/gim, '[B]');
data = data.replace(/<\/(?:b|strong)>/gim, '[/B]');
// [I]
data = data.replace(/<(?:i|em)>/gim, '[I]');
data = data.replace(/<\/(?:i|em)>/gim, '[/I]');
// [U]
data = data.replace(/<u>/gim, '[U]');
data = data.replace(/<\/u>/gim, '[/U]');
// [IMG]
data = data.replace(/<img\s{1}.*?src\s{0,1}=\s{0,1}["'](.+?)["']/gim, '[IMG="$1"]');
// [FONT]
data = data.replace(/<(?:span|div|p) (?:.*?)style="font-family:\s+(.+?);*">([\s\S]*?)<\/(?:span|div|p)>/gim, '[FONT="$1"]$2[/FONT]');
// [SIZE]
data = data.replace(/<(?:span|div|p) (?:.*?)style="font-size:\s+(.+?);*">([\s\S]*?)<\/(?:span|div|p)>/gim, '[SIZE="$1"]$2[/SIZE]');
// [COLOR]
data = data.replace(/<(?:span|div|p) (?:.*?)style="color:\s+(.+?);*">([\s\S]*?)<\/(?:span|div|p)>/gim, '[COLOR="$1"]$2[/COLOR]');
// [CENTER]
data = data.replace(/<(?:span|div|p) (?:.*?)style="text-align:\s*?center.*?">([\s\S]*?)<\/(?:span|div|p)>/gim, '[CENTER]$1[/CENTER]');
// [LEFT]
data = data.replace(/<(?:span|div|p) (?:.*?)style="text-align:\s*?left.*?">([\s\S]*?)<\/(?:span|div|p)>/gim, '[LEFT]$1[/LEFT]');
// [RIGHT]
data = data.replace(/<(?:span|div|p) (?:.*?)style="text-align:\s*?right.*?">([\s\S]*?)<\/(?:span|div|p)>/gim, '[RIGHT]$1[/RIGHT]');
// [BLOCK]
data = data.replace(/<blockquote>/gim, '[BLOCK]');
data = data.replace(/<\/blockquote>/gim, '[/BLOCK]');
// Ordered List [OL]
data = data.replace(/<(?:ol)>/gim, '[LIST=1]');
data = data.replace(/<\/(?:ol)>/gim, '[/LIST]');
// Unordered List [UL]
data = data.replace(/<(?:ul)>/gim, '[LIST]');
data = data.replace(/<\/(?:ul)>/gim, '[/LIST]');
// [LI]
data = data.replace(/<li\s{0,1}.*?>([\s\S]*?)<\/li>/gim, '[*]$1');
// [SPOILER]
data = data.replace(/<span .*?style=(["']background-color:(.+?);+\s*?color:(.+?);+\s*?["']|class="comspoiler")>([\s\S]*?)<\/span>/gim, '[SPOILER]$4[/SPOILER]');
// [INDENT]
data = data.replace(/<(?:span|div|p) (?:.*?)style="margin-left:\s+(.+?);*">([\s\S]*?)<\/(?:span|div|p)>/gim, '[INDENT="$1"]$2[/INDENT]');
// Remove remaining tags.
data = data.replace(/(<[^>]+>)/gm, '');
return data;
},
/*
* Makes any necessary changes to a piece of HTML for insertion in the
* editor selection position.
* @param {String} html The HTML to be fixed.
*/
FixHtml: function(html) {
return html;
}
};
// This Data Processor doesn't support <p>, so let's use <br>.
FCKConfig.EnterMode = 'br';
// To avoid pasting invalid markup (which is discarded in any case), let's
// force pasting to plain text.
FCKConfig.ForcePasteAsPlainText = true;
// Rename the "Source" buttom to "BBCode".
FCKToolbarItems.RegisterItem('Source', new FCKToolbarButton('Source', 'BBCode', null, FCK_TOOLBARITEM_ICONTEXT, true, true, 1));
// Let's enforce the toolbar to the limits of this Data Processor. A custom
// toolbar set may be defined in the configuration file with more or less entries.
FCKConfig.ToolbarSets["Default"] = [
['Source'],
['Bold', 'Italic', 'Underline', 'Link'],
['About']
];
以上的程式碼是由http://cksource.com/forums/viewtopic.php?f=5&t=14234&start=0&view=print複製的。
這樣子就衍生支援到 超連結、字體樣式、貼圖、置左、置中、置右、項目清單等,但是因為很多功能都不能用了,因此 demo 也整理了可以使用的 Toolbar
FCKConfig.ToolbarSets["bbcode"] = [ ['Source', 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteWord'], ['FitWindow', 'ShowBlocks', '-', 'About'], ['Undo', 'Redo', '-', 'SelectAll', 'RemoveFormat'], '/', ['Bold', 'Italic', 'Underline'], ['OrderedList', 'UnorderedList', '-', 'Outdent'], ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyFull'], ['Link', 'Unlink'], ['Image','Rule'], ['TextColor', 'BGColor'] ];
這裡應該就完成了,但是有一個很有趣的部份,就是寫入資料庫的值從原始的HTML標籤變成了BBCODE所以直接讀取出來效果是不會出現的,demo建議可以使用上面 fckplugin.js 的部份 CODE抽出來做成一個 JS 來作頁面的轉換方式,相關的 CODE 如下
function ConvertToHTML(data)
{
// Convert < and > to their HTML entities.
data = data.replace(/</g, '<');
data = data.replace(/>/g, '>');
// Convert line breaks to <br>.
data = data.replace(/(?:\r\n|\n|\r)/g, '<br>');
// [url]
data = data.replace(/\[url\](.+?)\[\/url]/gi, '<a href="$1">$1</a>');
data = data.replace(/\[url\=([^\]]+)](.+?)\[\/url]/gi, '<a href="$1">$2</a>');
// [b]
data = data.replace(/\[B\]([\s\S]*?)\[\/B\]/gim, '<b>$1</b>');
// [i]
data = data.replace(/\[I\]([\s\S]*?)\[\/I\]/gim, '<i>$1</i>');
// [u]
data = data.replace(/\[U\]([\s\S]*?)\[\/U\]/gim, '<u>$1</u>');
// [IMG]
data = data.replace(/\[IMG\=["']([^\]]+)["']\]/gim, '<img src="$1">');
// [FONT]
data = data.replace(/\[FONT\=["']([^\]]+)["']\]([\s\S]*?)\[\/FONT\]/gim, '<span style="font-family: $1;">$2</span>');
// [SIZE]
data = data.replace(/\[SIZE\=["']([^\]]+)["']\]([\s\S]*?)\[\/SIZE\]/gim, '<span style="font-size: $1;">$2</span>');
// [COLOR]
data = data.replace(/\[COLOR\=["']([^\]]+)["']\]([\s\S]*?)\[\/COLOR\]/gim, '<span style="color: $1;">$2</span>');
// [CENTER]
data = data.replace(/\[CENTER\]([\s\S]*?)\[\/CENTER\]/gim, '<span style="text-align:center;">$2</span>');
// [LEFT]
data = data.replace(/\[LEFT\]([\s\S]*?)\[\/LEFT\]/gim, '<span style="text-align:left;">$2</span>');
// [RIGHT]
data = data.replace(/\[RIGHT\]([\s\S]*?)\[\/RIGHT\]/gim, '<span style="text-align:right;">$2</span>');
//LI - goes before parents replacement [OL] or [UL]
data = data.replace(/\[\*\]([\s\S]*?)\[\*\]/gim, '<li>$1</li>');
data = data.replace(/\[\*\]([\s\S]*?)\[\/LIST\]/gim, '<li>$1</li>[/LIST]');
// Ordered List [OL]
data = data.replace(/\[LIST\=1\]([\s\S]*?)\[\/LIST\]/gim, '<ol>$1</ol>');
// Unordered List [UL]
data = data.replace(/\[LIST\]([\s\S]*?)\[\/LIST\]/gim, '<ul>$1</ul>');
// [spoiler]
data = data.replace(/\[SPOILER\]([\s\S]*?)\[\/SPOILER\]/gim, '<span style="background-color:#666666;color:#666666;">$1</span>');
// [INDENT]
data = data.replace(/\[INDENT\=["']([^\]]+)["']\]([\s\S]*?)\[\/INDENT\]/gim, '<div style="margin-left: $1;">$2</div>');
return data;
}
以上應該就完整了,希望對你有幫助。








Roslyn 魔法工坊:打造你的 Source Generator [2025-12-20]開課 共7H
回應討論