结构 jsp + jquery + kafir-bb
在数据库存为ubbCode 前台显示为解析为htmlCode
kefir-bb架包: http://sourceforge.net/projects/kefir-bb/files/kefir-bb/kefir-bb-0.4/kefir-bb-0.4.jar/download
前台 test.jsp
<%@ page language="java" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>ubb测试</title> <style type="text/css"> .editor-toolbar {width:100%; height: 20px;padding: 2px;background: #eee;} .editor-mask {position:absolute; width:100%; height:2000px; left:0; top:0; z-index:100; display:none;} .editor-button {display: block;float: left;overflow: hidden;margin: 0 2px;text-indent: -10000em;width: 21px;height: 20px;cursor: pointer;background: transparent url() left top no-repeat;} .editor-button:hover {background-color: #b7d4ff;} .editor-btnLink {background-image: url(http://static.l99.com/skin/default/images/message/bb_link.gif);} .editor-btnImage {background-image: url(http://static.l99.com/skin/default/images/message/bb_image.gif);} .editor-content{background-color: #eeeeee;border: 2px #cccccc solid; padding: 2px;} .editor-content a.close{position:absolute;right:3px;top:5px;background: url(http://static.l99.com/skin/default/images/record_delete.gif) no-repeat; width: 16px;height: 16px; } .answers{text-align: right;} </style> </head> <body> <h1>jQuery的UBB</h1> <div> <form action="EditBBcode_save.action" method="post"> <div style="width: 60%;"> <textarea id="editor" name="bbCode" style="width:100%;" rows="10" >[b]样例文字。[/b]</textarea> </div> <input id="submit" type="submit" value="提交表单" /> </form> </div> </div> <script type="text/javascript" src="js/jquery-1.3.2-min.js"></script> <script type="text/javascript" src="js/test/ubb_tools_test.js"></script> <script type="text/javascript"> $("document").ready(function(){ $.TextAreaUbb("editor"); }); </script> </body> </html>
前台 ubb_tools_test.js:
/** * 插入UBB */ (function($) { $.fn.extend({ makeLink : function () { return this.click(function(){ var b = $(this), f = UbbOption.ubbObject.getSelection(), c = b.offset(), d = document, t; if(jQuery.trim(f) === ""){return;} c.top += b.height(); if (d.selection && d.selection.createRange) { t = d.selection.createRange(); } UbbOption.ubbObject.showPrompt("LINK", function () { var e = this.txt.val(); if(e == "")return; var g = "[url=" + e + "]" + f + "[/url]"; UbbOption.ubbObject.insertText(g, t); UbbOption.ubbObject.ubbText.keyup(); }, c); }); }, makeImage : function () { return this.click(function(){ var b = $(this), g = UbbOption.ubbObject.getSelection(), c = b.offset(), d = document, t; c.top += b.height(); if (d.selection && d.selection.createRange) { t = d.selection.createRange(); } UbbOption.ubbObject.showPrompt("IMG", function () { var h = this.txt.val(); if(h == "")return; var g = "[img=" + h + "]"; var it = this.txt.attr("title"); if(it){ g = "[img=" + h + " imgtitle=" + it + "]"; } UbbOption.ubbObject.insertText(g, t); UbbOption.ubbObject.ubbText.keyup(); }, c); }); } }); var UbbOption = { ubbObject:null }; /** * UBB初始化 */ $.TextAreaUbb = function(ubbId){ if(ubbId == 'undefined'){ return; } if(UbbOption.ubbObject != null){ return; } UbbOption.ubbObject = this; createUbb(); function createUbb(){ UbbOption.ubbObject.ubbText = $("#" + ubbId); UbbOption.ubbObject.ubbText.wrap("<div id=\"" + ubbId + "-wrapper\"></div>").parent("div").addClass("editor-wrapper"); UbbOption.ubbObject.toolbar = $("<div id=\"" + ubbId + "-toolbar\"></div>").insertBefore(UbbOption.ubbObject.ubbText).addClass("editor-toolbar"); btnLink = makeButton("btnLink", "链接").makeLink(); btnImage = makeButton("btnImage", "插入图片").makeImage(); $("<div style=\"padding-top: 5px; font-size: 12px;\">(还可以输入<span class=\"text_orange\" id=\"ubb_text_warning\">400</span>个字)</div>").appendTo(UbbOption.ubbObject.toolbar); } function makeButton(a, b, c) { return $("<a href=\"javascript:void(0);\" title=\"" + b + "\" class=\"editor-button editor-" + a + "\" " + (c?"id=\"" + c +"\"":"") + " >" + b + "</a>").appendTo(UbbOption.ubbObject.toolbar); } UbbOption.ubbObject.getSelection = function (){ var j = window, f = document, g = UbbOption.ubbObject.ubbText.get(0); if (UbbOption.ubbObject.def(g.selectionStart)) { return g.value.substr(g.selectionStart, g.selectionEnd - g.selectionStart); } else { if (f.selection && f.selection.createRange) { return f.selection.createRange().text; } else { if (j.getSelection) { return window.getSelection() + ""; } } } return null; }; UbbOption.ubbObject.def = function() { if (arguments.length == 0) { return true; } if (arguments.length == 1) { return (typeof (arguments[0]) != "undefined"); } for (var a = 0; a < arguments.length; ++a) { if (!UbbOption.ubbObject.def(arguments[a])) { return false; } } return true; } UbbOption.ubbObject.showPrompt = function(a, e, b, d) { new Prompt().show(a, e, b, d); }; UbbOption.ubbObject.insertText = function(l, t) { var n = this, i = document, j = UbbOption.ubbObject.ubbText.get(0); if (UbbOption.ubbObject.def(j.selectionStart)) { var b = j.selectionStart + 0; j.value = j.value.substr(0, j.selectionStart) + l + j.value.substr(j.selectionEnd); } else { if (i.selection && i.selection.createRange && t && t.text!="") { var g = i.selection.createRange(); t.text = l.replace(/\r?\n/g, "\r\n"); g.select(); } else { j.value += l; } } }; }; /** * UBB遮盖层 */ var Prompt = function () { var a = this; if (!Prompt.instance) { a.mask = $("<div class=\"editor-mask\"></div>").appendTo(document.body).hide(); a.boxy = $("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" class=\"boxy-wrapper\"><tr><td class=\"top-left\"></td><td class=\"top\"></td><td class=\"top-right\"></td></tr><tr><td class=\"boxy-left\"></td><td class=\"boxy-inner\"><div class=\"editor-content\" style=\"display: block;\"></div></td><td class=\"boxy-right\"></td></tr><tr><td class=\"bottom-left\"></td><td class=\"bottom\"></td><td class=\"bottom-right\"></td></tr></table>").css({position:"absolute", zIndex:101}).appendTo(document.body).hide(); a.container = $('.editor-content', a.boxy); a.cancel = $("<a class=\"close\" href=\"javascript:void(0);\"> </a>").appendTo(a.container).click(function () { a.hide(); }); a.mask.click(function(){ a.cancel.click(); }); } return Prompt.instance; }; Prompt.prototype = {mask:$(), container:$(), ok:$(), cancel:$(), onOk:function (a) { }, show:function (e, c, d) { var b = this; b.onOk = c; switch(e){ case "LINK":{ b.container.append($("<div class=\"subcontext\">插入链接</div>")); b.cencontext = $("<div class=\"cencontext\"></div>").appendTo(b.container); b.supcontext = $("<div class=\"answers\"></div>").appendTo(b.container); b.txt = $("<input type=\"text\" value=\"http://\" />").appendTo(b.cencontext).css({width:"200px", margin:"5px 0"}).keypress(function (b) { if (b.keyCode == 13) { b.ok.click(); } }); b.cencontext.prepend("请输入链接地址:"); b.ok = $("<input type=\"button\" value=\"确定\" />").appendTo(b.supcontext).css({background:"#FC5A0A", color:"#FFFFFF", width:"40px"}).click(function () { if ($.isFunction(b.onOk)) { b.onOk.call(b); } b.hide(); }); break; }; case "IMG":{ b.container.append($("<div class=\"subcontext\">网络图片</div>")); b.cencontext = $("<div class=\"cencontext\"></div>").appendTo(b.container); b.netpic = $("<div id=\"net_pic\"></div>").appendTo(b.cencontext); b.txt = $("<input type=\"text\" value=\"http://\" />").appendTo(b.netpic).css({width:"200px", margin:"5px 0"}).keypress(function (b) { if (b.keyCode == 13) { b.ok.click(); } }); b.netpic.append("<div class=\"clear\"></div>"); b.supcontext = $("<div class=\"answers\"></div>").appendTo(b.netpic); b.netpic.prepend("请输入图片地址:"); b.ok = $("<input type=\"button\" value=\"确定\" />").appendTo(b.supcontext).css({background:"#FC5A0A", color:"#FFFFFF", width:"40px"}).click(function () { if ($.isFunction(b.onOk)) { b.onOk.call(b); } b.hide(); }); break; }; } if (d) { b.boxy.css(d); } b.mask.fadeIn("fast"); b.boxy.slideDown("fast"); }, hide:function () { this.boxy.slideUp("fast",function(){$(this).remove();}); this.mask.fadeOut("fast",function(){$(this).remove();}); }}; })(jQuery);
前台生成的ubbCode数据
[img=http://www.google.cn/images/nav_logo7.png]\r\n[url=http://www.google.cn/images/nav_logo7.png][img=http://www.google.cn/images/nav_logo7.png][/url]
后台 bbcode_test.xml
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://kefir-bb.sourceforge.net/schemas" xsi:schemaLocation="http://kefir-bb.sourceforge.net/schemas http://kefir-bb.sourceforge.net/schemas/kefir-bb-0.4.xsd"> <!-- XML escape symbols --> <scope name="escapeXml"> <coderef name="amp"/> <coderef name="apos"/> <coderef name="lt"/> <coderef name="gt"/> <coderef name="quot"/> </scope> <code name="amp" priority="100"> <pattern>&</pattern> <template>&amp;</template> </code> <code name="apos" priority="100"> <pattern>'</pattern> <template>&apos;</template> </code> <code name="lt" priority="100"> <pattern><</pattern> <template>&lt;</template> </code> <code name="gt" priority="100"> <pattern>></pattern> <template>&gt;</template> </code> <code name="quot" priority="100"> <pattern>"</pattern> <template>&quot;</template> </code> <!-- Root scope. This scope uses when processor started work and by default, if not set other scope --> <scope name="ROOT" parent="escapeXml"> <coderef name="noubb"/> <coderef name="nbsp"/> <coderef name="br1"/> <coderef name="br2"/> <coderef name="br3"/> <coderef name="br4"/> <coderef name="br5"/> <coderef name="slash"/> <coderef name="left_square_bracket"/> <coderef name="right_square_bracket"/> <coderef name="bold"/> <coderef name="u"/> <coderef name="s"/> <coderef name="i"/> <coderef name="code"/> <coderef name="img1"/> <coderef name="img2"/> <coderef name="img3"/> <coderef name="url1"/> <coderef name="url2"/> <coderef name="url3"/> <coderef name="url4"/> <coderef name="url5"/> <coderef name="color"/> <coderef name="size"/> <coderef name="symbol"/> <coderef name="comment"/> <coderef name="ul"/> <coderef name="li"/> <coderef name="p1"/> <coderef name="p2"/> <coderef name="p3"/> <coderef name="div1"/> <coderef name="div2"/> <coderef name="span1"/> <coderef name="span2"/> <coderef name="span3"/> </scope> <code name="noubb" priority="10"> <pattern>[noubb]<var parse="false"/>[/noubb]</pattern> <template><var/></template> </code> <!-- line feed characters --> <code name="br1" priority="3"> <pattern>

</pattern> <template><br/></template> </code> <code name="br2" priority="2"> <pattern>
</pattern> <template><br/></template> </code> <code name="br3" priority="1"> <pattern>
</pattern> <template><br/></template> </code> <code name="br4" priority="0"> <pattern>
</pattern> <template><br/></template> </code> <code name="br5" priority="4"> <pattern>[br /]</pattern> <template><br/></template> </code> <!-- Escape bb-code symbols double slash to slash slash + square bracket to square bracket --> <code name="slash" priority="10"> <pattern>\\</pattern> <template>\</template> </code> <code name="left_square_bracket" priority="9"> <pattern>\[</pattern> <template>[</template> </code> <code name="right_square_bracket" priority="9"> <pattern>\]</pattern> <template>]</template> </code> <!-- Simple formatting --> <code name="bold"> <pattern>[b]<var/>[/b]</pattern> <template><span style="font-weight:bold;"><var/></span></template> </code> <code name="u"> <pattern>[u]<var/>[/u]</pattern> <template><span style="text-decoration:underline;"><var/></span></template> </code> <code name="s"> <pattern>[s]<var/>[/s]</pattern> <template><span style="text-decoration:line-through;"><var/></span></template> </code> <code name="i"> <pattern>[i]<var/>[/i]</pattern> <template><span style="font-style:italic;"><var/></span></template> </code> <!-- Quote code block --> <code name="code"> <pattern>[code]<var scope="codeScope"/>[/code]</pattern> <template><pre><var/></pre></template> </code> <scope name="codeScope" parent="escapeXml"> <coderef name="br1"/> <coderef name="br2"/> <coderef name="br3"/> <coderef name="br4"/> <coderef name="br5"/> <coderef name="slash"/> <coderef name="left_square_bracket"/> <coderef name="right_square_bracket"/> <coderef name="symbol"/> <coderef name="comment"/> </scope> <!-- Insert image --> <code name="img1" priority="3"> <pattern>[img=http://<var name="src" scope="escapeXml"/> imgtitle=<var name="imgtitle" scope="escapeXml"/> imgclass=<var name="imgclass" scope="escapeXml"/>]</pattern> <template><img src="http://<var name="src"/>" title="<var name="imgtitle"/>" class="<var name="imgclass"/>" alt="图片载入中..."/></template> </code> <code name="img2" priority="2"> <pattern>[img=http://<var name="src" scope="escapeXml"/> imgtitle=<var name="imgtitle" scope="escapeXml"/>]</pattern> <template><img src="http://<var name="src"/>" title="<var name="imgtitle"/>" class="ubb_img" alt="图片载入中..."/></template> </code> <code name="img3" priority="1"> <pattern>[img=http://<var scope="escapeXml"/>]</pattern> <template><img src="http://<var/>" class="ubb_img" alt="图片载入中..."/></template> </code> <!-- Links. http, malto protocols --> <code name="url1" priority="6"> <pattern>[url=http://<var name="url" scope="escapeXml"/>]<var name="text"/>[/url]</pattern> <template><a href="http://<var name="url"/>" target="_blank" ><var name="text"/></a></template> </code> <code name="url2" priority="3"> <pattern>[url]http://<var name="url" scope="escapeXml"/>[/url]</pattern> <template><a href="http://<var name="url"/>" target="_blank" >http://<var name="url"/></a></template> </code> <code name="url3" priority="5"> <pattern>[url=mailto:<var name="url" scope="escapeXml"/>]<var name="text"/>[/url]</pattern> <template><a href="mailto:<var name="url"/>" target="_blank" ><var name="text"/></a></template> </code> <code name="url4" priority="7"> <pattern>[url=<var name="url" scope="escapeXml"/> style=<var name="style" scope="escapeXml" />]<var name="text"/>[/url]</pattern> <template><a href="<var name="url"/>" style="<var name="style"/>" target="_blank" ><var name="text"/></a></template> </code> <code name="url5" priority="7"> <pattern>[url=<var name="url" scope="escapeXml"/> class=<var name="class" scope="escapeXml" />]<var name="text"/>[/url]</pattern> <template><a href="<var name="url"/>" class="<var name="class"/>" target="_blank" ><var name="text"/></a></template> </code> <!-- Font color --> <code name="color"> <pattern>[color=<var name="color" scope="escapeXml"/>]<var name="text"/>[/color]</pattern> <template><span style="color:<var name="color"/>;"><var name="text"/></span></template> </code> <!-- Comment --> <code name="comment"> <pattern>[*<var parse="false"/>*]</pattern> <template/> </code> <!-- Font size --> <code name="size"> <pattern>[size=<var name="size" scope="escapeXml"/>]<var name="text"/>[/size]</pattern> <template><span style="font-size:<var name="size"/>;"><var name="text"/></span></template> </code> <!-- Special html symbols --> <code name="symbol"> <pattern>[symbol=<var scope="escapeXml"/>/]</pattern> <template>&<var/>;</template> </code> <!-- extend --> <code name="nbsp"> <pattern> </pattern> <template>&nbsp;</template> </code> <code name="ul"> <pattern>[ul=<var name="style" scope="escapeXml"/>]<var name="text"/>[/ul]</pattern> <template><ul style="<var name="style"/>"><var name="text"/></ul></template> </code> <code name="li"> <pattern>[li=<var name="style" scope="escapeXml"/>]<var name="text"/>[/li]</pattern> <template><li style="<var name="style"/>"><var name="text"/></li></template> </code> <code name="p1"> <pattern>[p=<var name="style" scope="escapeXml"/>]<var name="text"/>[/p]</pattern> <template><p style="<var name="style"/>"><var name="text"/></p></template> </code> <code name="p2"> <pattern>[p]<var name="text"/>[/p]</pattern> <template><p><var name="text"/></p></template> </code> <code name="p3"> <pattern>[p class=<var name="class" scope="escapeXml"/>]<var name="text"/>[/p]</pattern> <template><p class="<var name="class"/>"><var name="text"/></p></template> </code> <code name="div1"> <pattern>[div=<var name="style" scope="escapeXml"/>]<var name="text"/>[/div]</pattern> <template><div style="<var name="style"/>"><var name="text"/></div></template> </code> <code name="div2"> <pattern>[div class=<var name="class" scope="escapeXml"/>]<var name="text"/>[/div]</pattern> <template><div class="<var name="class"/>"><var name="text"/></div></template> </code> <code name="span1" priority="3"> <pattern>[span=<var name="style" scope="escapeXml"/>]<var name="text"/>[/span]</pattern> <template><span style="<var name="style"/>"><var name="text"/></span></template> </code> <code name="span2" priority="2"> <pattern>[span class=<var name="class" scope="escapeXml"/>]<var name="text"/>[/span]</pattern> <template><span class="<var name="class"/>" ><var name="text"/></span></template> </code> <code name="span3" priority="1"> <pattern>[span title=<var name="title" scope="escapeXml"/> class=<var name="class" scope="escapeXml"/>]<var name="text"/>[/span]</pattern> <template><span class="<var name="class"/>" title="<var name="title"/>" ><var name="text"/></span></template> </code> </configuration>
后台java解析
TextProcessor processor = BBProcessorFactory.getInstance().createFromResource("bbcode_test.xml"); String htmlCode = processor.process(bbCode);
最后生成html代码
<img src="http://www.google.cn/images/nav_logo7.png" alt="图片载入中..."/><br/><a href="http://www.google.cn/images/nav_logo7.png" target="_blank" ><img src="http://www.google.cn/images/nav_logo7.png" alt="图片载入中..."/></a>