/**
 * @author Willko Cheng
 * @version 0.1
 * IE 6/7 Firefox 2
 * [* Opera 9 Safari 3]
 */
TWBBS_EDITOR_ROOT = "images/index/";
if (typeof TWBBS_EDITOR_ROOT == "undefined") {
    TWBBS_EDITOR_ROOT = './';
}
var TWBBS_EDITOR_DEBUG = false;

function twbbsEditor(textarea, charset){
    charset = charset || "UTF-8";
    if (typeof textarea == 'string') {
        textarea = this.$(textarea);
    }
    
    if (textarea && textarea.tagName.toLowerCase() == 'textarea') {
        this.textarea = textarea;
    }
    else {
        alert("编辑器必须是textarea对象或者textarea元素的ID!");
        return;
    }
    
    this.charset = charset;
    
    this._loadStyle();
    var userAgent = navigator.userAgent;
    this.browser = {
        mozilla: /mozilla/i.test(userAgent) && !/(compatible|webkit)/i.test(userAgent),
        msie: /msie/i.test(userAgent) && !/opera/i.test(userAgent),
        safari: /webkit/i.test(userAgent),
        opera: /opera/i.test(userAgent)
    };
    
    return this;
}

twbbsEditor.prototype = {
    $: function(id){
        return document.getElementById(id);
    },
    
    preventDefault: function(e){
        if (e.preventDefault) {
            e.preventDefault();
        }
        else {
            e.returnValue = false;
        }
        return this;
    },
    
    calculateOffset: function(obj, offset){
        var ret = 0;
        while (obj) {
            ret += obj[offset];
            obj = obj.offsetParent;
        }
        return ret;
    },
    
    exec: function(cmd, argument){
        try {
            if (this.browser.msie && this._range) {
				if (!this.inArray(cmd.toLowerCase(), ["createlink"])) {
					this._win.focus();
				}
                this._range.execCommand(cmd, false, argument);
            }
            else {
                this._win.focus();
                this.doc.execCommand(cmd, false, argument);
            }
        } 
        catch (e) {
            if (TWBBS_EDITOR_DEBUG) {
                alert(cmd);
                alert(e);
            }
        }
        
        return this;
    },
    
    query: function(cmd){
        try {
            if (this._range && this.browser.msie) {
                return this._range.queryCommandState(cmd);
            }
            else {
                this._win.focus();
                return this.doc.queryCommandState(cmd);
            }
        } 
        catch (e) {
            if (TWBBS_EDITOR_DEBUG) {
                alert(cmd);
                alert(e);
            }
        }
    },
    
    getStateValue: function(cmd){
        try {
            return this.doc.queryCommandValue(cmd);
        } 
        catch (e) {
            if (TWBBS_EDITOR_DEBUG) {
                alert(cmd);
                alert(e);
            }
        }
    },
    
    hasClass: function(ele, clsName){
        var reg = new RegExp("\\b" + clsName + "\\b");
        return reg.test(ele.className);
    },
    
    addClass: function(ele, clsName){
        if (!this.hasClass(ele, clsName)) {
            var space = ele.className.length > 0 ? " " : "";
            ele.className += space + clsName;
        }
        return this;
    },
    
    removeClass: function(ele, clsName){
        var reg = new RegExp("\\b" + clsName + "\\b");
        ele.className = ele.className.replace(reg, " ");
        return this;
    },
    
    toggleClass: function(ele, clsName){
        if (this.hasClass(ele, clsName)) {
            this.removeClass(ele, clsName);
        }
        else {
            this.addClass(ele, clsName);
        }
        return this;
    },
    
    getStyle: function(obj, attr){
        if (obj.style[attr]) {
            ret = obj.style[attr];
        }
        else 
            if (obj.currentStyle) {
                ret = obj.currentStyle[attr];
            }
            else {
                var domStyle = document.defaultView.getComputedStyle(obj, null);
                ret = domStyle.getPropertyValue(attr);
            }
        return ret;
    },
    
    fadeIn: function(obj, speed){
        speed = speed || 10;
        var me = this;
        var opacity = this.getStyle(obj, "opacity") * 100;
        var display = this.getStyle(obj, "display");
        if (this.browser.msie) {
            var filter = this.getStyle(obj, "filter");
            var result = filter.match(/alpha\(opacity=(\d+)\)/i);
            if (result) {
                opacity = parseInt(result[1]);
            }
        }
        if (display == "none" || display == "") {
            opacity = 0;
            obj.style.display = "block";
        }
        opacity += 10;
        if (opacity <= 100) {
        
            if (this.browser.msie) {
                obj.style.filter = filter.replace(/alpha\([^)]+\)/i, "") + "alpha(opacity=" + opacity + ")";
            }
            else {
                obj.style.opacity = opacity / 100;
            }
            setTimeout(function(){
                me.fadeIn.call(me, obj, speed);
            }, speed);
        }
        else {
            if (this.browser.msie) {
                obj.style.filter = filter.replace(/alpha\([^)]+\)/i, "");
            }
        }
    },
    
    fadeOut: function(obj, speed){
        speed = speed || 10;
        var me = this;
        var opacity = this.getStyle(obj, "opacity") * 100;
        var display = this.getStyle(obj, "display");
        if (this.browser.msie) {
            var filter = this.getStyle(obj, "filter");
            var result = filter.match(/alpha\(opacity=(\d+)\)/i);
            if (result) {
                opacity = parseInt(result[1]);
            }
            else {
                opacity = 100;
            }
        }
        opacity -= 10;
        if (opacity <= 0) {
            obj.style.display = "none";
        }
        if (display != "none" && display != "") {
            if (this.browser.msie) {
                obj.style.filter = filter.replace(/alpha\([^)]+\)/i, "") + "alpha(opacity=" + opacity + ")";
            }
            else {
                obj.style.opacity = opacity / 100;
            }
            
            setTimeout(function(){
                me.fadeOut.call(me, obj, speed);
            }, speed);
        }
    },
    insertUbb: function(tag, attr, content){
        var openTag = "[" + tag;
        openTag += attr ? "=" + attr : "";
        openTag += "]";
        var closeTag = "[/" + tag + "]";
        var clsTagLen = closeTag.length;
        var opTagLen = openTag.length;
        var t = this.textarea;
        
        if (this.browser.msie) {
            this._range.text = openTag + (content || this.selectText) + closeTag;
            this._range.move("character", -clsTagLen);
            this._range.select();
        }
        else 
            if (typeof t.selectionStart != "undefined") {
                var start = t.selectionStart;
                var end = t.selectionEnd;
                var c = t.value.substr(start, end - start);
                t.value = t.value.substr(0, start) + openTag + (content || c) + closeTag + t.value.substr(end);
                content = content || "";
                t.selectionStart = start + opTagLen + c.length + content.length;
                t.selectionEnd = start + opTagLen + c.length + content.length;
                t.focus();
            }
            else {
                t.value += openTag + (content || "") + closeTag;
            }
        
        return this;
    },
    
    insertUbbCode: function(code, offset){
        var t = this.textarea;
        offset = offset || 0;
        if (this.browser.msie) {
            this._range.text = code;
            this._range.move("character", offset);
            this._range.select();
        }
        else 
            if (typeof t.selectionStart != "undefined") {
                var start = t.selectionStart;
                var end = t.selectionEnd;
                t.value = t.value.substr(0, start) + code + t.value.substr(end);
                t.selectionStart = start + code.length + offset;
                t.selectionEnd = start + code.length + offset;
                t.focus();
            }
            else {
                t.value += code;
            }
        
        return this;
    },
    
    insertHtml: function(html){
        try {
            if (this.browser.msie && this._range) {
                this._win.focus();
                this._range.pasteHTML(html);
                this._range.collapse(false);
                this._range.select();
            }
            else {
                this.exec("insertHTML", html);
            }
        } 
        catch (e) {
            if (TWBBS_EDITOR_DEBUG) {
                alert(e);
            }
        }
        
        return this;
    },
    
    render: function(){
        var outbox = this.outbox = document.createElement("div");
        var toolbar = this.toolbar = document.createElement("div");
        var editor = this.editor = document.createElement("iframe");
        var brume = this.brume = document.createElement("div");
        var win = this.win = document.createElement("div");
        var statusbar = this.statusbar = document.createElement("div");
        var me = this;
		
        outbox.id = "twbbsEditorOutbox";
        toolbar.id = "twbbsEditorToolbar";
        editor.id = "twbbsEditor";
        editor.name = "twbbsEditor";
        brume.id = "twbbsEditorBrume";
        win.id = "twbbsEditorWin";
        statusbar.className = "twbbsEditorStatusBar";
        
        toolbar.style.height = "26px";
        toolbar.style.borderBottom = "1px solid #CAD9EA";
        
        if (this.browser.msie) {
            // ie6's bug
            document.body.insertAdjacentElement("afterBegin", win);
			this.addEvent(window.top, 'resize', function() {
				me.contract().expand();
				}
			);
        }
        else {
            document.body.appendChild(win);
        }
        
        editor.border = 0;
        editor.frameBorder = 0;
        editor.marginWidth = 0;
        editor.marginHeight = 0;
        editor.width = '100%';
        editor.src = 'about:blank';
        
        outbox.appendChild(toolbar);
        outbox.appendChild(editor);
        outbox.appendChild(brume);
        
        var ele = this.textarea;
        this.data = {
            textarea: {
                offsetWidth: ele.offsetWidth,
                offsetHeight: ele.offsetHeight - 10
            }
        };
        
        var txt = this.data.textarea;
        
        this.outbox.style.width = txt.offsetWidth + "px";
       	this.outbox.style.height = txt.offsetHeight + "px";
        
        this.textarea.parentNode.replaceChild(outbox, this.textarea);
        outbox.appendChild(this.textarea);
        
        this.data.outbox = {
            top: this.calculateOffset(this.outbox, 'offsetTop'),
            left: this.calculateOffset(this.outbox, 'offsetLeft')
        };
        this.textarea.style.display = "none";
        this._initEditor()._initToolbar()._initStatusbar().mode = 'Design';
        this.isDesign = true;
        
        var offset = 0;
        if (this.browser.msie) {
            offset = -2;
        }
        this.textarea.style.height = this.outbox.clientHeight - this.toolbar.offsetHeight - this.statusbar.offsetHeight + offset + "px";
        this.textarea.style.width = "100%";
        //editor.style.height = this.outbox.clientHeight - this.toolbar.offsetHeight - this.statusbar.offsetHeight + "px";
        editor.style.height = txt.offsetHeight - 53 + "px" ;
        
        // for firefox's bug
        this.editor.style.display = "none";
        this.editor.style.display = "block";
        
        this.render = function(){
            return this;
        };
        return this;
    },
    
    toggle: function(){
        this.toggleBrume();
        if (this.mode == 'Design') {
            var root = this.doc.body;
            var childs = root.childNodes;
            var len = childs.length;
            var html = '';
            for (var n = 0; n < len; n++) {
                html += this.dom2ubb(childs[n]);
            }
            this.textarea.value = html;
            this.editor.style.display = "none";
            this.textarea.style.display = "block";
            this.textarea.focus();
            this.mode = 'Source';
            this.isDesign = false;
            this.cancelButtonStatus();
        }
        else {
            this.doc.body.innerHTML = this.ubb2html(this.textarea.value);
            this.editor.style.display = "block";
            this.textarea.style.display = "none";
            this._win.focus();
            this.mode = 'Design';
            this.isDesign = true;
        }
        this.toggleBrume();
        return this;
    },
    
    getContent: function(){
        if (this.doc) {
            if (this.isDesign) {
                this.toggle();
            }
        }
        return this;
    },
	
	getContent2: function(){
		var selVal = document.getElementById("forumId");
		var selVal = selVal.options[selVal.selectedIndex].text;
		if (selVal == "請選擇"){
			alert("請選擇討論區版塊");
			return false;
		}
        if (this.doc) {
            if (this.isDesign) {
                this.toggle();
            }
        }
        return this;
    },

	contract: function() {
		var outbox = this.outbox;
		var textarea = this.textarea;
		var editor = this.editor;
		var height = '';
		
		if (this.isDesign) {
			height = this.getStyle(editor, 'height');
		} else {
			height = this.getStyle(textarea, 'height');
		}
		height = parseInt(height) - 50;
		if(height  > 0){
			textarea.style.height = height + "px";
			editor.style.height = height + "px";
			outbox.style.height = parseInt(this.getStyle(outbox, 'height')) + -50 + "px";
		}
		return this;
	},
	
	expand: function() {
		var outbox = this.outbox;
		var textarea = this.textarea;
		var editor = this.editor;
		var height = '';

		outbox.style.height = parseInt(this.getStyle(outbox, 'height')) + 50 + "px";
		
		if (this.isDesign) {
			height = this.getStyle(editor, 'height');
		} else {
			height = this.getStyle(textarea, 'height');
		}
		height = parseInt(height);
		textarea.style.height = height + 50 + "px";
		editor.style.height = height + 50 + "px";
		return this;
	},
    
    _loadStyle: function(){
        var link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = TWBBS_EDITOR_ROOT + "twbbseditor.css";
        document.getElementsByTagName("head")[0].appendChild(link);
        this._loadStyle = function(){
            return this;
        };
        return this;
    },
    
    _initEditor: function(){
        var editor = this.editor;
        var me = this;
        
        if (editor.contentDocument) {
            this.doc = editor.contentDocument;
            this.doc.designMode = "On";
        }
        else {
            this.doc = editor.contentWindow.document;
            this.doc.designMode = "On";
            this.doc = editor.contentWindow.document;
        }
        
        this._win = editor.contentWindow;
        
        var defaultHtml = [];
        defaultHtml.push('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');
        defaultHtml.push('<html xmlns="http://www.w3.org/1999/xhtml">');
        defaultHtml.push('<head>');
        defaultHtml.push('<style type="text/css">');
       	defaultHtml.push('body{margin:10px;font-size:10pt;font-family:Arial;}');
        defaultHtml.push('blockquote{background-color:#F6F6F6;border:1px solid #DDDDDD;color:#333333;padding:10px;}');
        defaultHtml.push('blockquote em{font-weight:bold;font-style:normal;display:block;}');
        defaultHtml.push('blockquote strong{font-weight:normal;}');
        defaultHtml.push('p{margin:0;}');
        defaultHtml.push('.tw_flash{background:url("' + TWBBS_EDITOR_ROOT + 'images/flash.gif") no-repeat center center;border: 1px solid #A9A9A9;}');
        defaultHtml.push('.tw_music{background:url("' + TWBBS_EDITOR_ROOT + 'images/music.gif") no-repeat center center;border: 1px solid #A9A9A9;}');
        defaultHtml.push('</style>');
        defaultHtml.push('<meta http-equiv="Content-Type" content="text/html; charset=');
        defaultHtml.push(this.charset);
        defaultHtml.push('" />');
        defaultHtml.push('<title>Editor</title>');
        defaultHtml.push('</head>');
        defaultHtml.push('<body>');
        defaultHtml.push(this.textarea.value);
        defaultHtml.push('</body>');
        defaultHtml.push('</html>');
        
        this.doc.open();
        this.doc.write(defaultHtml.join(""));
        this.doc.close();
        
        var processButtonStatusHandler = function(e){
            e = e || window.event;
            me.processButtonStatus.call(me, e, true);
        };
        
        this.addEvent(this.doc.body, 'mouseup', processButtonStatusHandler);
        this.addEvent(this.doc, 'keyup', processButtonStatusHandler);
        
        return this;
    },
    
    _initToolbar: function(){
        var me = this;
        var html = [];
        
        html.push('<table border="0" cellspacing="0" cellpadding="0">');
        html.push("<tr>");
        
        // bold
        html.push("<td>");
        html.push('<a href="#tw_bold"><img alt="b" title="文本加粗" src="' + TWBBS_EDITOR_ROOT + 'images/bold.gif" /></a>');
        html.push("</td>");
        
        // italic
        html.push("<td>");
        html.push('<a href="#tw_italic"><img alt="i" title="文本斜體" src="' + TWBBS_EDITOR_ROOT + 'images/italic.gif" /></a>');
        html.push("</td>");
        
        // underline
        html.push("<td>");
        html.push('<a href="#tw_underline"><img alt="u" title="文本下劃線" src="' + TWBBS_EDITOR_ROOT + 'images/underline.gif" /></a>');
        html.push("</td>");
        
        // strikethrough
        html.push("<td>");
        html.push('<a href="#tw_strikethrough"><img alt="s through" title="文本中劃線" src="' + TWBBS_EDITOR_ROOT + 'images/strikethrough.gif" /></a>');
        html.push("</td>");
        
        // forecolor
        html.push("<td>");
        html.push('<a href="#tw_forecolor" class="menuPop"><img alt="color" title="文本顏色" src="' + TWBBS_EDITOR_ROOT + 'images/forecolor.gif" /><br /><img id="twbbsEditorForecolorStatus" src="' + TWBBS_EDITOR_ROOT + 'images/dot.gif" style="height:4px;width:20px;background-color:#000000;" /></a>');
        html.push("</td>");
        
        // fontsize
        html.push("<td>");
        html.push('<a href="#tw_fontsize"><img alt="size" title="文本大小" src="' + TWBBS_EDITOR_ROOT + 'images/fontsize.gif" /></a>');
        html.push("</td>");
        
        // createlink
        html.push("<td>");
        html.push('<a href="#tw_createlink"><img alt="url" title="插入超級連結" src="' + TWBBS_EDITOR_ROOT + 'images/createlink.gif" /></a>');
        html.push("</td>");
        
        // createemail
        html.push("<td>");
        html.push('<a href="#tw_createemail"><img alt="url" title="插入電子郵件" src="' + TWBBS_EDITOR_ROOT + 'images/createemail.gif" /></a>');
        html.push("</td>");
        
        // insertimage
        html.push("<td>");
        html.push('<a href="#tw_insertimage"><img alt="img" title="插入圖片" src="' + TWBBS_EDITOR_ROOT + 'images/insertimage.gif" /></a>');
        html.push("</td>");
        
        // insertmusic
        html.push("<td>");
        html.push('<a href="#tw_insertmusic"><img alt="music" title="插入音頻" src="' + TWBBS_EDITOR_ROOT + 'images/insertmusic.gif" /></a>');
        html.push("</td>");
        
        // insertflash
        html.push("<td>");
        html.push('<a href="#tw_insertflash"><img alt="flash" title="插入FLASH" src="' + TWBBS_EDITOR_ROOT + 'images/insertflash.gif" /></a>');
        html.push("</td>");
        
        // insertquote
        html.push("<td>");
        html.push('<a href="#tw_insertquote"><img alt="quote" title="插入引用" src="' + TWBBS_EDITOR_ROOT + 'images/insertquote.gif" /></a>');
        html.push("</td>");
        
        // inserttable
        html.push("<td>");
        html.push('<a href="#tw_inserttable"><img alt="table" title="插入表格" src="' + TWBBS_EDITOR_ROOT + 'images/inserttable.gif" /></a>');
        html.push("</td>");
        
        // inserthorizontalline
        html.push("<td>");
        html.push('<a href="#tw_inserthorizontalline"><img alt="hr" title="插入水平線" src="' + TWBBS_EDITOR_ROOT + 'images/inserthorizontalline.gif" /></a>');
        html.push("</td>");
        
        // alignleft
        html.push("<td>");
        html.push('<a href="#tw_alignleft"><img alt="left" title="左對齊" src="' + TWBBS_EDITOR_ROOT + 'images/alignleft.gif" /></a>');
        html.push("</td>");
        
        // aligncenter
        html.push("<td>");
        html.push('<a href="#tw_aligncenter"><img alt="center" title="居中對齊" src="' + TWBBS_EDITOR_ROOT + 'images/aligncenter.gif" /></a>');
        html.push("</td>");
        
        // alignright
        html.push("<td>");
        html.push('<a href="#tw_alignright"><img alt="right" title="右對齊" src="' + TWBBS_EDITOR_ROOT + 'images/alignright.gif" /></a>');
        html.push("</td>");
        
        // orderedlist
        html.push("<td>");
        html.push('<a href="#tw_orderedlist"><img alt="list" title="插入數字編號" src="' + TWBBS_EDITOR_ROOT + 'images/orderedlist.gif" /></a>');
        html.push("</td>");
        
        // unorderedlist
        html.push("<td>");
        html.push('<a href="#tw_unorderedlist"><img alt="list" title="插入項目編號" src="' + TWBBS_EDITOR_ROOT + 'images/unorderedlist.gif" /></a>');
        html.push("</td>");
        
        html.push("</tr>");
        html.push("</table>");
        this.toolbar.innerHTML = html.join("");
        
        /**
         * bind handler
         */
        var eles = this.toolbar.getElementsByTagName("a");
        var len = eles.length;
        var toolbarEles = this.toolbarEles = {};
        for (var n = 0; n < len; n++) {
            var ele = eles[n];
            var type = ele.href.match(/#(.+)$/)[1];
            
            switch (type) {
                case "tw_bold":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.boldHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['bold'] = ele;
                    break;
                    
                case "tw_italic":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.italicHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['italic'] = ele;
                    break;
                    
                case "tw_underline":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.underlineHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['underline'] = ele;
                    break;
                    
                case "tw_forecolor":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.forecolorShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                    
                case "tw_insertimage":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.insertImageShowHandler.call(me, e, "#FF3300");
                        me.preventDefault(e);
                    };
                    break;
                case "tw_alignleft":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.alignLeftHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['justifyLeft'] = ele;
                    break;
                case "tw_aligncenter":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.alignCenterHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['justifyCenter'] = ele;
                    break;
                case "tw_alignright":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.alignRightHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['justifyRight'] = ele;
                    break;
                case "tw_createlink":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.createLinkShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                case "tw_createemail":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.createEmailShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                case "tw_fontsize":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.fontsizeShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                case "tw_orderedlist":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.orderedListHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['insertOrderedList'] = ele;
                    break;
                case "tw_unorderedlist":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.unorderedListHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['insertUnorderedList'] = ele;
                    break;
                case "tw_inserthorizontalline":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.insertHorizontalLineShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                case "tw_strikethrough":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.strikeThroughHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    toolbarEles['strikeThrough'] = ele;
                    break;
                case "tw_inserttable":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.insertTableShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                case "tw_insertmusic":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.insertMusicShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                case "tw_insertquote":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.insertQuoteShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
                case "tw_insertflash":
                    ele.onclick = function(e){
                        e = e || window.event;
                        me.insertFlashShowHandler.call(me, e);
                        me.preventDefault(e);
                    };
                    break;
            }
        }
        return this;
    },
    
    _initStatusbar: function(){
        var status = this.statusbar;
        var html = ['<table border="0" cellspaceing="0" cellpadding="0" width="100%">', '<tr valign="middle">', '<td>', '<input type="radio" name="twbbsEditorModeRadio" id="twbbsEditorModeSource" checked="true" value="Design" /><label for="twbbsEditorModeSource">預覽模式</label>', '<input type="radio" name="twbbsEditorModeRadio" id="twbbsEditorModeDesign" value="Source" /><label for="twbbsEditorModeDesign">代碼模式</label>', '</td>', '<td style="text-align:right;padding-top:5px;">', '<img src="', TWBBS_EDITOR_ROOT + 'images/expand.gif', '" id="twbbsEditorExpandButton" alt="expand" title="加大" />', '&nbsp;&nbsp;', '<img src="', TWBBS_EDITOR_ROOT + 'images/contract.gif', '" id="twbbsEditorContractButton" alt="contract" title="減少" />', '&nbsp;</td>', '</tr>', '</table>'];
        status.innerHTML = html.join("");
		 this.outbox.appendChild(status);
        var me = this;
		
       function toggleMode(e){
                e = e || window.event;
                var target = e.target || e.srcElement;
                if (target.value != me.mode) {
                    me.toggle.call(me);
                }
            }
		this.$("twbbsEditorModeSource").onclick = toggleMode;
		this.$("twbbsEditorModeDesign").onclick = toggleMode;
		
		this.$("twbbsEditorContractButton").onclick = function(e) {
			e = e || window.event;
			
			me.contract.call(me);
		};
		this.$("twbbsEditorExpandButton").onclick = function(e) {
			e = e || window.event;
			me.expand.call(me);
		};
       
        return this;
    },
    
    _getSelection: function(){
        if (this.isDesign) {
            var win = this._win;
            var doc = this.doc;
            win.focus();
        }
        else {
            var win = window;
            var doc = window.document;
            this.textarea.focus();
        }
        
        if (win.getSelection) {
            this._selection = win.getSelection();
        }
        else 
            if (doc.getSelection) {
                this._selection = doc.getSelection();
            }
            else 
                if (doc.selection) {
                    this._selection = doc.selection;
                }
        return this;
    },
    
    _getRange: function(){
        if (this.isDesign) {
            var win = this._win;
            var doc = this.doc;
        }
        else {
            var win = window;
            var doc = window.document;
        }
        this._getSelection();
        if (this._selection.getRangeAt) {
            this._range = this._selection.getRangeAt(0);
        }
        else 
            if (this._selection.createRange) {
                this._range = this._selection.createRange();
            }
            else { // Safari!
                var range = doc.createRange();
                range.setStart(this._selection.anchorNode, this._selection.anchorOffset);
                range.setEnd(this._selection.focusNode, this._selection.focusOffset);
                this._range = range;
            }
        this._getSelectText();
        return this;
    },
    
    _getSelectText: function(){
        if (this._selection.createRange) {
            this.selectText = this._range.text;
        }
        else 
            if (this._selection.toString) {
                this.selectText = this._selection.toString();
            }
            else {
                this.selectText = '';
            }
        return this;
    },
    
    _emptyRange: function(){
        this._selection = null;
        this._range = null;
        this.selectText = null;
        return this;
    },
    
    
    
    dom2ubb: function(node){
        var ret = [];
        var childs = node.childNodes;
        var len = childs.length;
        var pushBr = false;
        var stopParse = false;
        
        if (node.nodeType == 1) {
            var stack = [];
            var sty = node.style;
            var cssText = sty.cssText;
            var content = [];
            switch (node.tagName) {
                case 'SPAN':
                    // mozilla
                    // bold italic underline strikethrough forecolor
                    var bold = /font-weight: bold\b/i;
                    var italic = /font-style: italic\b/i;
                    var underline = /text-decoration:.*?underline\b/i;
                    var strikethrough = /text-decoration:.*?line-through\b/i;
                    var forecolor = /color: rgb\(([^,]+), ([^,]+), ([^,]+)\)/i;
                    var forecolor2 = /color: (#[0-9a-f]+)/i;
                    if (bold.test(cssText)) {
                        stack.push({
                            tag: "b"
                        });
                    }
                    if (italic.test(cssText)) {
                        stack.push({
                            tag: "i"
                        });
                    }
                    if (underline.test(cssText)) {
                        stack.push({
                            tag: "u"
                        });
                    }
                    if (strikethrough.test(cssText)) {
                        stack.push({
                            tag: "s"
                        });
                    }
                    var rgb = cssText.match(forecolor);
                    if (rgb) {
                        var red = parseInt(rgb[1]);
                        var green = parseInt(rgb[2]);
                        var blue = parseInt(rgb[3]);
                        red = red > 0xf ? red.toString(16) : "0" + red.toString(16);
                        green = green > 0xf ? green.toString(16) : "0" + green.toString(16);
                        blue = blue > 0xf ? blue.toString(16) : "0" + blue.toString(16);
                        var color = "#" + red + green + blue;
                        stack.push({
                            tag: "color",
                            attr: color
                        });
                    }
                    // ie
                    var color = cssText.match(forecolor2);
                    if (color) {
                        stack.push({
                            tag: "color",
                            attr: color[1]
                        });
                    }
                    break;
                    
                case "STRONG":
                    // ie 
                    // bold
                    stack.push({
                        tag: "b"
                    });
                    break;
                    
                case "EM":
                    // ie
                    // italic
                    stack.push({
                        tag: "i"
                    });
                    break;
                    
                case "U":
                    // ie
                    // underline
                    stack.push({
                        tag: "u"
                    });
                    break;
                case "STRIKE":
                    // ie
                    // strikethrough
                    stack.push({
                        tag: "s"
                    });
                    break;
                case "FONT":
                    // size
                    if (node.size) {
                        stack.push({
                            tag: "size",
                            attr: node.size
                        });
                    }
                    if (node.color) {
                        // ie forecolor
                        stack.push({
                            tag: "color",
                            attr: node.color
                        });
                    }
                    break;
                case "BR":
                    content.push("\n");
                    break;
                case "A":
                    stack.push({
                        tag: "url",
                        attr: node.href
                    });
                    break;
                case "IMG":
                    if (node.className == "tw_flash") {
                        var width = /width: (\d+)/i;
                        var height = /height: (\d+)/i;
                        width = (cssText.match(width) || [])[1];
                        height = (cssText.match(height) || [])[1];
                        if (width && height) {
                            stack.push({
                                tag: "flash",
                                attr: width + "," + height
                            });
                        }
                        else {
                            stack.push({
                                tag: "flash"
                            });
                        }
                        
                        content.push(node.alt);
                    }
                    else 
                        if (node.className == "tw_music") {
                            stack.push({
                                tag: "music"
                            });
                            content.push(node.alt);
                        }
                        else {
                            var width = /width: (\d+)/i;
                            var height = /height: (\d+)/i;
                            width = (cssText.match(width) || [])[1];
                            height = (cssText.match(height) || [])[1];
                            var obj = {
                                tag: "img"
                            };
                            if (width && height) {
                                obj.attr = width + "," + height;
                            }
                            else 
                                if (node.width && node.height) {
                                    //ie
                                    obj.attr = node.width + "," + node.height;
                                }
                            stack.push(obj);
                            content.push(node.src);
                        }
                    
                    break;
                // music
                case "/EMBED":
                    // dummy for ie
                    break;
                case "EMBED":
                    stack.push({
                        tag: "music"
                    });
                    content.push(node.src);
                    
                    break;
                case "BLOCKQUOTE":
                    stack.push({
                        tag: "quote"
                    });
                    var title = node.childNodes[2] || document.createElement("em");
                    var cont = node.childNodes[4] || document.createElement("strong");
                    title = title.innerText || title.textContent;
                    content.push("[i]" + title + "[/i]");
                    var childs = cont.childNodes;
                    var len = childs.length;
                    for (var n = 0; n < len; n++) {
                        content.push(this.dom2ubb(childs[n]));
                    }
                    stopParse = true;
                    break;
                case "HR":
                    stack.push({
                        tag: "hr",
                        attr: "1," + node.width + ",left,#000000"
                    });
                    break;
                case "DIV":
                    // mozilla
                    // align
                    var align = /text-align: (left|center|right)/i;
                    var result = cssText.match(align);
                    if (result) {
                        stack.push({
                            tag: "align",
                            attr: result[1]
                        });
                    }
                    break;
                case "P":
                    // ie
                    // align
                    if (node.align) {
                        stack.push({
                            tag: "align",
                            attr: node.align
                        });
                    } else {
						pushBr = true;
					}
                    break;
                case "OL":
                    stack.push({
                        tag: "list",
                        attr: "1"
                    });
                    var childs = node.childNodes;
                    var len = childs.length;
                    for (var n = 0; n < len; n++) {
                        content.push("[*]" + this.dom2ubb(childs[n]) + "[/*]");
                    }
                    stopParse = true;
                    break;
                case "UL":
                    stack.push({
                        tag: "list"
                    });
                    var childs = node.childNodes;
                    var len = childs.length;
                    for (var n = 0; n < len; n++) {
                        content.push("[*]" + this.dom2ubb(childs[n]) + "[/*]");
                    }
                    stopParse = true;
                    break;
                case "LI":
                    // dummy
                    break;
                case "TABLE":
                    stack.push({
                        tag: "table",
                        attr: node.width
                    });
                    break;
                case "TBODY":
                    // dummy
                    break;
                case "TR":
                    stack.push({
                        tag: "tr"
                    });
                    break;
                case "TD":
                    stack.push({
                        tag: "td"
                    });
                    break;
                default:
                    if (TWBBS_EDITOR_DEBUG) {
                        alert(node.tagName);
                    }
            }
            if (!stopParse) {
                var childs = node.childNodes;
                var len = childs.length;
                for (var n = 0; n < len; n++) {
                    content.push(this.dom2ubb(childs[n]));
                }
            }
            
            if (pushBr) {
                content.push("\n");
            }
            ret.push(this._stack2ubb(stack, content.join("")));
        }
        else 
            if (node.nodeType == 3) {
                ret.push(node.nodeValue);
            }
        return ret.join("");
    },
    
    _stack2ubb: function(stack, content){
        var len = stack.length;
        var ret = [];
        var obj;
        for (var n = 0; n < len; n++) {
            obj = stack[n];
            switch (obj.tag) {
                default:
                    ret.push("[" + obj.tag);
                    if (obj.attr) {
                        ret.push("=" + obj.attr);
                    }
                    ret.push("]");
            }
        }
        ret.push(content);
        for (var n = len - 1; n >= 0; n--) {
            switch (stack[n].tag) {
                default:
                    ret.push("[/" + stack[n].tag + "]");
            }
        }
        return ret.join("");
    },
    
    ubb2html: function(code){
        function ubb(str){
            this.str = str;
        }
        ubb.prototype = {
            convert: function(reg, str){
                this.str = this.str.replace(reg, str);
                return this;
            },
            
            hr: function(){
                var reg = /\[hr=(\d*),(\d*%?),(left|center|right),([#0-9a-f]{7})\]\[\/hr\]/igm;
                var str = '<hr size="$1" width="$2" align="$3" color="$4" />';
                this.convert(reg, str);
                return this;
            },
            
            color: function(){
                var reg = /\[color=([\s\S]*?)\]([\s\S]+?)\[\/color\]/igm;
                var str = '<span style="color:$1">$2</span>';
                this.convert(reg, str);
                if (reg.test(this.str)) {
                    this.color();
                }
                return this;
            },
            
            b: function(){
                var reg = /\[b\]([\s\S]*?)\[\/b\]/igm;
                var str = '<strong>$1</strong>';
                this.convert(reg, str);
                if (reg.test(this.str)) {
                    this.b();
                }
                return this;
            },
            
            i: function(){
                var reg = /\[i\]([\s\S]*?)\[\/i\]/igm;
                var str = '<em>$1</em>';
                this.convert(reg, str);
                if (reg.test(this.str)) {
                    this.i();
                }
                return this;
            },
            
            u: function(){
                var reg = /\[u\]([\s\S]*?)\[\/u\]/igm;
                var str = '<u>$1</u>';
                this.convert(reg, str);
                if (reg.test(this.str)) {
                    this.u();
                }
                return this;
            },
            
            s: function(){
                var reg = /\[s\]([\s\S]*?)\[\/s\]/igm;
                var str = '<strike>$1</strike>';
                this.convert(reg, str);
                if (reg.test(this.str)) {
                    this.s();
                }
                return this;
            },
            
            align: function(){
                var reg = /\[align=(left|center|right)\]([\s\S]*?)\[\/align\]/igm;
                var str = '<p align="$1">$2</p>';
                this.convert(reg, str);
                if (reg.test(this.str)) {
                    this.align();
                }
                return this;
            },
            
            size: function(){
                var reg = /\[size=(\d+)\]([\s\S]*?)\[\/size\]/igm;
                var str = '<font size="$1">$2</font>';
                this.convert(reg, str);
                if (reg.test(this.str)) {
                    this.size();
                }
                return this;
            },
            
            url: function(){
                var reg = /\[url=([^\]]+?)\](.*?)\[\/url\]/igm;
                var str = '<a href="$1">$2</a>';
                this.convert(reg, str);
                return this;
            },
            
            list: function(){
                var reg = /\[\*\]([\s\S]*?)\[\/\*\]/igm;
                var str = '<li>$1</li>';
                this.convert(reg, str);
                
                var reg = /\[list\]([\s\S]*?)\[\/list\]/igm;
                var str = '<ul>$1</ul>';
                this.convert(reg, str);
                
                var reg = /\[list=1\]([\s\S]*?)\[\/list\]/igm;
                var str = '<ol>$1</ol>';
                this.convert(reg, str);
                
                return this;
            },
            
            quote: function(){
                var reg = /\[quote\](<em>[\s\S]*?<\/em>)([\s\S]*?)\[\/quote\]/igm;
                var str = '<blockquote>QUOTE:<hr />$1<br /><strong>$2</strong><hr /></blockquote>';
                this.convert(reg, str);
                return this;
            },
            
            img: function(){
                var reg = /\[img\]([\s\S]*?)\[\/img\]/igm;
                var str = '<img src="$1" />';
                this.convert(reg, str);
                
                var reg = /\[img=(\d*),(\d*)\]([^\[]+?)\[\/img\]/igm;
                var str = '<img src="$3" style="width: $1px; height: $2px;" />';
                this.convert(reg, str);
                return this;
            },
            
            music: function(){
                var reg = /\[music\]([\s\S]*?)\[\/music\]/igm;
                var str = '<img class="tw_music" src="' + TWBBS_EDITOR_ROOT + "images/spacer.gif" + '" style="width: 200px; height: 40px;" alt="$1" title="$1" />';
                this.convert(reg, str);
                return this;
            },
            
            table: function(){
                var reg = /\[table=(\d+%?)\]([\s\S]*?)\[\/table\]/igm;
                var str = '<table width="$1" cellspacing="0" cellpadding="0" border="0" bgcolor="#eeeeee" style="border-top: 1px solid #000; border-left: 1px solid #000;">$2</table>';
                this.convert(reg, str);
                
                var reg = /\[tr\]([\s\S]*?)\[\/tr\]/igm;
                var str = '<tr>$1</tr>';
                this.convert(reg, str);
                
                var reg = /\[td\]([\s\S]*?)\[\/td\]/igm;
                var str = '<td style="border-right: 1px solid #000; border-bottom: 1px solid #000;">$1</td>';
                this.convert(reg, str);
                
                return this;
            },
            
            flash: function(){
                var reg = /\[flash=(\d+),(\d+)\]([\s\S]*?)\[\/flash\]/igm;
                var str = '<img class="tw_flash" src="' + TWBBS_EDITOR_ROOT + "images/spacer.gif" + '" style="width: $1px; height: $2px;" alt="$3" title="$3" />';
                this.convert(reg, str);
                var reg = /\[flash\]([\s\S]*?)\[\/flash\]/igm;
                var str = '<img class="tw_flash" src="' + TWBBS_EDITOR_ROOT + "images/spacer.gif" + '" alt="$1" title="$1" width="50" height="50" />';
                this.convert(reg, str);
                return this;
            }
        };
        var u = new ubb(this.htmlspecialchars(code));
        
        return this.nl2br(u.hr().color().b().i().u().s().align().size().url().list().quote().img().music().table().flash().str);
    },
    
    html2dom: function(html){
        var d = document.createElement("div");
        d.innerHTML = html;
        return d.childNodes;
    },
    
    nl2br: function(str){
        return str.replace(/\n/ig, "<br />");
    },
    
    br2nl: function(str){
        return str.replace(/<br>/ig, "\n");
    },
    
    htmlspecialchars: function(str){
        return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    },
    
    htmlspecialcharsdecode: function(str){
        return str.replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")
    },
    
    parseRgb: function(rgb){
        rgb = rgb + "";
		
        var forecolor = /rgb\(([^,]+), ([^,]+), ([^,]+)\)/i;
		var r, g, b;
        
        var result = rgb.match(forecolor);
        if (result) {
            r = parseInt(result[1]);
            g = parseInt(result[2]);
            b = parseInt(result[3]);
        }
        else {
			rgb = parseInt(rgb).toString(16);
			if (rgb.length == 6) {
				r = parseInt(rgb.substr(4, 2), 16);
				g = parseInt(rgb.substr(2, 2), 16);
				b = parseInt(rgb.substr(0, 2), 16);
			} else if(rgb.length == 4) {
				r = parseInt(rgb.substr(2, 2), 16);
				g = parseInt(rgb.substr(0, 2), 16);
				b = 0;
			} else {
				r = parseInt(rgb.substr(0, 2), 16);
				g = 0;
				b = 0;
			}
        }
 		r = r > 0xf ? r.toString(16) : "0" + r.toString(16);
        g = g > 0xf ? g.toString(16) : "0" + g.toString(16);
        b = b > 0xf ? b.toString(16) : "0" + b.toString(16);
        return color = "#" + r + g + b;
    },
    
    addEvent: function(ele, event, handler){
        if (ele.addEventListener) {
            ele.addEventListener(event, handler, false);
        }
        else 
            if (ele.attachEvent) {
                ele.attachEvent("on" + event, handler);
            }
        return this;
    },
    
    delEvent: function(ele, event, handler){
        if (ele.removeEventListener) {
            ele.removeEventListener(event, handler, false);
        }
        else 
            if (ele.detachEvent) {
                ele.detachEvent("on" + event, handler);
            }
    },
    
    inArray: function(needle, haystack){
        var isArray = needle instanceof Array ? true : false;
        for (var prop in haystack) {
            var val = haystack[prop];
            if (isArray) {
                if (this.inArray(val, needle)) {
                    return true;
                }
            }
            else 
                if (val == needle) {
                    return true;
                }
        }
        return false;
    },
    
    displayWin: function(offsetObj, html, width, confrimHandler, cancleHandler, focusId){
        var offLeft = this.calculateOffset(offsetObj, 'offsetLeft');
        var offTop = this.calculateOffset(offsetObj, 'offsetTop');
        var win = this.win;
        var sty = win.style;
        var reTop = offTop + offsetObj.offsetHeight;
        var reLeft = offLeft;
        var me = this;
        html = '<form id="twbbsEditorWinConfrim">' + html;
        html += '<p style="text-align:center;">';
        if (confrimHandler) {
            html += '<input type="submit" value="確定" />&nbsp;';
        }
        if (cancleHandler) {
            html += '<input type="button" value="取消" id="twbbsEditorWinCancle" />';
        }
        html += '</p></form>';
        
        win.innerHTML = html;
        sty.width = width + "px";
        sty.left = reLeft + "px";
        sty.top = reTop + "px";
        this.fadeIn(win);
        
        if (focusId) {
            var focus = this.$(focusId);
            focus.focus();
            if (focus.select) {
                focus.select();
            }
        }
        
        if (confrimHandler) {
            this.$("twbbsEditorWinConfrim").onsubmit = confrimHandler;
        }
        if (cancleHandler) {
            this.$("twbbsEditorWinCancle").onclick = cancleHandler;
        }
        
        return this;
    },
    
    closeWin: function(e){
        e = e || window.event;
        this.fadeOut(this.win);
        return this;
    },
    
    toggleBrume: function(){
        var sty = this.brume.style;
        
        if (sty.display == "block") {
            sty.display = "none";
        }
        else {
            sty.display = "block";
            sty.height = this.outbox.offsetHeight + "px";
        }
        return this;
    },
    
    createColorer: function(){
        if (!this._colorer) {
            var colorer = this._colorer = document.createElement("div");
            var html = [];
            colorer.className = "twbbsEditorColorOutbox";
            html.push('<table border="0" cellspacing="0" cellpadding="0">');
            html.push('<tr>');
            html.push('<td><a href="#000000" style="background-color:#000000;" title="#000000">&nbsp;</a></td>');
            html.push('<td><a href="#993300" style="background-color:#993300;" title="#993300">&nbsp;</a></td>');
            html.push('<td><a href="#333300" style="background-color:#333300;" title="#333300">&nbsp;</a></td>');
            html.push('<td><a href="#003300" style="background-color:#003300;" title="#003300">&nbsp;</a></td>');
            html.push('<td><a href="#003366" style="background-color:#003366;" title="#003366">&nbsp;</a></td>');
            html.push('<td><a href="#000080" style="background-color:#000080;" title="#000080">&nbsp;</a></td>');
            html.push('<td><a href="#333399" style="background-color:#333399;" title="#333399">&nbsp;</a></td>');
            html.push('<td><a href="#333333" style="background-color:#333333;" title="#333333">&nbsp;</a></td>');
            html.push('</tr>');
            html.push('<tr>');
            html.push('<td><a href="#800000" style="background-color:#800000;" title="#800000">&nbsp;</a></td>');
            html.push('<td><a href="#ff6600" style="background-color:#ff6600;" title="#ff6600">&nbsp;</a></td>');
            html.push('<td><a href="#808000" style="background-color:#808000;" title="#808000">&nbsp;</a></td>');
            html.push('<td><a href="#808080" style="background-color:#808080;" title="#808080">&nbsp;</a></td>');
            html.push('<td><a href="#008080" style="background-color:#008080;" title="#008080">&nbsp;</a></td>');
            html.push('<td><a href="#0000ff" style="background-color:#0000ff;" title="#0000ff">&nbsp;</a></td>');
            html.push('<td><a href="#666699" style="background-color:#666699;" title="#666699">&nbsp;</a></td>');
            html.push('<td><a href="#808080" style="background-color:#808080;" title="#808080">&nbsp;</a></td>');
            html.push('</tr>');
            html.push('<tr>');
            html.push('<td><a href="#ff0000" style="background-color:#ff0000;" title="#ff0000">&nbsp;</a></td>');
            html.push('<td><a href="#ff9900" style="background-color:#ff9900;" title="#ff9900">&nbsp;</a></td>');
            html.push('<td><a href="#99cc00" style="background-color:#99cc00;" title="#99cc00">&nbsp;</a></td>');
            html.push('<td><a href="#339966" style="background-color:#339966;" title="#339966">&nbsp;</a></td>');
            html.push('<td><a href="#33cccc" style="background-color:#33cccc;" title="#33cccc">&nbsp;</a></td>');
            html.push('<td><a href="#3366ff" style="background-color:#3366ff;" title="#3366ff">&nbsp;</a></td>');
            html.push('<td><a href="#800080" style="background-color:#800080;" title="#800080">&nbsp;</a></td>');
            html.push('<td><a href="#999999" style="background-color:#999999;" title="#999999">&nbsp;</a></td>');
            html.push('</tr>');
            html.push('<tr>');
            html.push('<td><a href="#ff00ff" style="background-color:#ff00ff;" title="#ff00ff">&nbsp;</a></td>');
            html.push('<td><a href="#ffcc00" style="background-color:#ffcc00;" title="#ffcc00">&nbsp;</a></td>');
            html.push('<td><a href="#ffff00" style="background-color:#ffff00;" title="#ffff00">&nbsp;</a></td>');
            html.push('<td><a href="#00ff00" style="background-color:#00ff00;" title="#00ff00">&nbsp;</a></td>');
            html.push('<td><a href="#00ffff" style="background-color:#00ffff;" title="#00ffff">&nbsp;</a></td>');
            html.push('<td><a href="#00ccff" style="background-color:#00ccff;" title="#00ccff">&nbsp;</a></td>');
            html.push('<td><a href="#993366" style="background-color:#993366;" title="#993366">&nbsp;</a></td>');
            html.push('<td><a href="#c0c0c0" style="background-color:#c0c0c0;" title="#c0c0c0">&nbsp;</a></td>');
            html.push('</tr>');
            html.push('<tr>');
            html.push('<td><a href="#ff99cc" style="background-color:#ff99cc;" title="#ff99cc">&nbsp;</a></td>');
            html.push('<td><a href="#ffcc99" style="background-color:#ffcc99;" title="#ffcc99">&nbsp;</a></td>');
            html.push('<td><a href="#ffff99" style="background-color:#ffff99;" title="#ffff99">&nbsp;</a></td>');
            html.push('<td><a href="#ccffcc" style="background-color:#ccffcc;" title="#ccffcc">&nbsp;</a></td>');
            html.push('<td><a href="#ccffff" style="background-color:#ccffff;" title="#ccffff">&nbsp;</a></td>');
            html.push('<td><a href="#99ccff" style="background-color:#99ccff;" title="#99ccff">&nbsp;</a></td>');
            html.push('<td><a href="#cc99ff" style="background-color:#cc99ff;" title="#cc99ff">&nbsp;</a></td>');
            html.push('<td><a href="#ffffff" style="background-color:#ffffff;" title="#ffffff">&nbsp;</a></td>');
            html.push('</tr>');
            html.push('<tr>');
            html.push('<td colspan="8" align="center"><input type="button" value="取消" /></td>');
            html.push('</tr>');
            html.push('</table>');
            
            colorer.innerHTML = html.join("");
            var inps = colorer.getElementsByTagName("input");
            var me = this;
            inps[0].onclick = function(){
                me.closeColorer.call(me);
            };
            if (this.browser.msie) {
                // ie6's bug
                document.body.insertAdjacentElement("afterBegin", colorer);
            }
            else {
                document.body.appendChild(colorer);
            }
			this.createColorer = function() {
				return this;
			};
        };
        return this;
    },
    
    displayColorer: function(reTop, reLeft, confrimHandler){
        this.createColorer();
        var sty = this._colorer.style;
        sty.left = reLeft + "px";
        sty.top = reTop + "px";
        this.fadeIn(this._colorer);
        
        var eles = this._colorer.getElementsByTagName("a");
        var len = eles.length;
        var str = '';
        var me = this;
        for (var n = 0; n < len; n++) {
            eles[n].onclick = function(e){
                e = e || window.event;
                var target = e.target || e.srcElement;
                var color = this.href.match(/(#.{6})$/)[0];
                
                confrimHandler(e, color);
                me.preventDefault(e);
            };
        }
        return this;
    },
    
    closeColorer: function(){
        this.fadeOut(this._colorer);
        return this;
    },
    
    processButtonStatus: function(filter, isEvent){
        if (isEvent) {
            if (filter.keyCode == 13) {
                return;
            }
            filter = null;
        }
        
        var cmd = ["bold", "italic", "underline", "justifyCenter", "justifyRight", "insertOrderedList", "insertUnorderedList", "strikeThrough"];
        var len = cmd.length;
        var filter = filter || [];
        var result = [];
        
        for (var n = 0; n < len; n++) {
            if (this.query(cmd[n])) {
                if (!this.inArray(cmd[n], filter)) {
                    result.push(cmd[n]);
                    filter.push(cmd[n]);
                }
            }
        }
        this.cancelButtonStatus(filter);
        
        var len = result.length;
        if (len) {
            for (var n = 0; n < len; n++) {
                var ele = this.toolbarEles[result[n]];
                this.addClass(ele, 'twbbsEditorButtonSelected');
            }
        }
        
		var curColor = this.getStateValue("forecolor");
		if (curColor) {
			var color = this.parseRgb(curColor);
		} else {
			var color = "#000000";
		}
		var status = this.$("twbbsEditorForecolorStatus");
			status.style.backgroundColor = color;
        return this;
    },
    
    cancelButtonStatus: function(filter){
        filter = filter || [];
        
        var eles = this.toolbarEles;
        for (var prop in eles) {
            if (!this.inArray(prop, filter)) {
                this.removeClass(eles[prop], "twbbsEditorButtonSelected");
            }
        }
        return this;
    },
    
    boldHandler: function(e){
        e = e || window.event;
        
        if (this.isDesign) {
            var filter = ["bold"];
            this.toggleClass(this.toolbarEles["bold"], "twbbsEditorButtonSelected").exec("bold", '').processButtonStatus(filter);
        }
        else {
            this._getRange().insertUbb("b")._emptyRange();
        }
        
        this.preventDefault(e);
    },
    
    italicHandler: function(e){
        e = e || window.event;
        
        if (this.isDesign) {
            var filter = ["italic"];
            this.toggleClass(this.toolbarEles["italic"], "twbbsEditorButtonSelected").exec('italic', '').processButtonStatus(filter);
        }
        else {
            this._getRange().insertUbb("i")._emptyRange();
        }
        
        this.preventDefault(e);
    },
    
    underlineHandler: function(e){
        e = e || window.event;
        if (this.isDesign) {
            var filter = ["underline"];
            this.toggleClass(this.toolbarEles["underline"], "twbbsEditorButtonSelected").exec('underline', '').processButtonStatus(filter);
            
        }
        else {
            this._getRange().insertUbb('u')._emptyRange();
        }
        this.preventDefault(e);
    },
    
    forecolorShowHandler: function(e){
        e = e || window.event;
        var target = e.target || e.srcElement;
        
        var reTop = this.calculateOffset(target, 'offsetTop') + target.offsetHeight;
        var reLeft = this.calculateOffset(target, 'offsetLeft');
        var me = this;
        var confrimHandler = function(e, color){
            e = e || window.event;
            
            me.forecolorHandler.call(me, e, color);
        };
        this.createColorer().displayColorer(reTop, reLeft, confrimHandler).preventDefault(e);
    },
    
    forecolorHandler: function(e, color){
        e = e || window.event;
        
        if (this.isDesign) {
            var status = this.$("twbbsEditorForecolorStatus");
            status.style.backgroundColor = color;
            this.exec('forecolor', color);
        }
        else {
            this._getRange().insertUbb('color', color)._emptyRange();
        }
        this.closeColorer().preventDefault(e);
    },
    
    insertImageShowHandler: function(e){
        e = e || window.event;
        
        var target = e.target || e.srcElement;
        var height = 115;
        var width = 230;
        var me = this;
        var html = [];
        html.push('<p>請輸入圖片連結的網址：<br />');
        html.push('<input type="text" id="twbbsEditorImage" value="http://" /><br />');
        html.push('<span style="font-size:11px;color:#999999;">例如:http://twbbs.net.tw/img/logo.gif</span></p>');
        var confrimHandler = function(e){
            e = e || window.event;
            me.insertImageHandler.call(me, e);
            me.closeWin();
            me._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin();
            me._emptyRange();
        };
        this._getRange().displayWin(target, html.join(""), width, confrimHandler, cancleHandler, 'twbbsEditorImage').preventDefault(e);
    },
    
    insertImageHandler: function(e){
        e = e || window.event;
        
        var img = this.$("twbbsEditorImage").value;
        
        if (img != '' && !/^http:\/\/$/i.test(img)) {
            if (!/^http:\/\//i.test(img)) {
                img = "http://" + img;
            }
            if (this.isDesign) {
                this.exec("InsertImage", img);
            }
            else {
                this.insertUbb("img", null, img);
            }
            
        }
        
        this.preventDefault(e);
    },
    
    alignLeftHandler: function(e){
        e = e || window.event;
        if (this.isDesign) {
            var filter = ["justifyLeft"];
            this.toggleClass(this.toolbarEles["justifyLeft"], "twbbsEditorButtonSelected").exec("justifyleft", "").processButtonStatus(["justifyLeft"]);
        }
        else {
            this._getRange().insertUbb("align", "left")._emptyRange();
        }
        
        this.preventDefault(e);
    },
    
    alignCenterHandler: function(e){
        e = e || window.event;
        if (this.isDesign) {
            var filter = ["justifyCenter"];
            this.toggleClass(this.toolbarEles["justifyCenter"], "twbbsEditorButtonSelected").exec("justifycenter", "").processButtonStatus(["justifyCenter"]);
        }
        else {
            this._getRange().insertUbb("align", "center")._emptyRange();
        }
        this.preventDefault(e);
    },
    
    alignRightHandler: function(e){
        e = e || window.event;
        if (this.isDesign) {
            var filter = ["justifyRight"];
            this.toggleClass(this.toolbarEles["justifyRight"], "twbbsEditorButtonSelected").exec("justifyright", "").processButtonStatus(["justifyRight"]);
        }
        else {
            this._getRange().insertUbb("align", "right")._emptyRange();
        }
        this.preventDefault(e);
    },
    
        createLinkShowHandler: function(e){
        e = e || window.event;
        var target = e.target || e.srcElement;
        var height = 130;
        var width = 230;
        var me = this;
        var html = [];
        var defaultTxt = '';
        this._getRange();
        var type = this._selection.type;
        html.push('<p>請輸入超連結的文本，如“我的首頁”<br />');
        html.push('<input type="text" id="twbbsEditorLinkText" value="' + (this.selectText || "") + '"/></p>');
        html.push('<p>請輸入超連結的網址<br />');
        html.push('<input type="text" id="twbbsEditorLink" value="http://" /></p>');
        var confrimHandler = function(e){
            e = e || window.event;
            me.createLinkHandler.call(me, e, type);
            me.closeWin()._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin()._emptyRange();
        };
        this.displayWin(target, html.join(""), width, confrimHandler, cancleHandler, 'twbbsEditorLinkText');
        this.preventDefault(e);
    },
    
    createLinkHandler: function(e, type){
        e = e || window.event;
        var txt = this.$("twbbsEditorLinkText").value;
        var link = this.$("twbbsEditorLink").value;
        
        if (link != '' && !/^http:\/\/$/i.test(link)) {
            txt = txt ? txt : link;
            if (!/^http:\/\//i.test(link)) {
                link = 'http://' + link;
            }
            
            if (this.isDesign) {
                if (this.selectText || type == "Control" || this._selection.rangeCount == 1) {
                    this.exec("createlink", link);
                }
                else {
                    var html = ['<a href="', link, '">', txt, '</a>'];
                    this.insertHtml(html.join(""));
                }
            }
            else {
                this.insertUbb("url", link, txt);
            }
            
        }
        this.preventDefault(e);
    },
    
    createEmailShowHandler: function(e){
        var target = e.target || e.srcElement;
        var height = 130;
        var width = 230;
        var me = this;
        var html = [];
        var defaultTxt = '';
        this._getRange();
        var type = this._selection.type;
        html.push('<p>請輸入超連結的文本<br />');
        html.push('<input type="text" id="twbbsEditorLinkText" value="' + this.selectText + '"/></p>');
        html.push('<p>請輸入超連結的電子郵箱<br />');
        html.push('<input type="text" id="twbbsEditorLink" /></p>');
        var confrimHandler = function(e){
            e = e || window.event;
            me.createEmailHandler.call(me, e);
            me.closeWin();
            me._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin();
            me._emptyRange();
        };
        this.displayWin(target, html.join(""), width, confrimHandler, cancleHandler, 'twbbsEditorLinkText');
        this.preventDefault(e);
    },
    
    createEmailHandler: function(e, type){
        e = e || window.event;
        var txt = this.$("twbbsEditorLinkText").value;
        var link = this.$("twbbsEditorLink").value;
        
        if (link != '' && !/^http:\/\/$/i.test(link)) {
            txt = txt ? txt : link;
            link = "mailto:" + link;
            if (this.isDesign) {
                if (this.selectText || type == "Control" || this._selection.rangeCount == 1) {
                    this.exec("createlink", link);
                }
                else {
                    var html = ['<a href="', link, '">', txt, '</a>'];
                    this.insertHtml(html.join(""));
                }
            }
            else {
                this.insertUbb("url", link, txt);
            }
        }
        this.preventDefault(e);
    },
    
    fontsizeShowHandler: function(e){
        var target = e.target || e.srcElement;
        var height = 165;
        var width = 50;
        var me = this;
        var html = [];
        html.push('<a href="#3" style="font-size:small;">1</a>');
        html.push('<a href="#4" style="font-size:medium;">2</a>');
        html.push('<a href="#5" style="font-size:large;">3</a>');
        html.push('<a href="#6" style="font-size:x-large;">4</a>');
        //        html.push('<a href="#5" style="font-size:large;">5</a>');
        //        html.push('<a href="#6" style="font-size:x-large;">6</a>');
        //        html.push('<a href="#7" style="font-size:xx-large;">7</a>');
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin();
        };
        this.displayWin(target, html.join(""), width, null, cancleHandler);
        var eles = this.win.getElementsByTagName("a");
        var len = eles.length;
        var confrimHandler = function(e){
            e = e || window.event;
            me.fontsizeHandler.call(me, e);
            me.closeWin().preventDefault(e);
        };
        
        for (var n = 0; n < len; n++) {
            eles[n].onclick = confrimHandler;
        }
        this.preventDefault(e);
    },
    
    fontsizeHandler: function(e){
        var target = e.target || e.srcElement;
        var size = (target.href.match(/#(\d+)$/) || [])[1];
        if (this.isDesign) {
            this.exec("fontsize", size);
        }
        else {
            this._getRange().insertUbb("size", size)._emptyRange();
        }
    },
    
    orderedListHandler: function(e){
        e = e || window.event;
        if (this.isDesign) {
            var filter = ["insertOrderedList"];
            this.toggleClass(this.toolbarEles["insertOrderedList"], "twbbsEditorButtonSelected").exec('insertorderedlist', '').processButtonStatus(["insertOrderedList"]);
        }
        else {
            this._getRange().insertUbbCode("[list=1][*]" + this.selectText + "[/*][/list]", -11)._emptyRange();
        }
        this.preventDefault(e);
    },
    
    unorderedListHandler: function(e){
        e = e || window.event;
        if (this.isDesign) {
            var filter = ["insertUnorderedList"];
            this.toggleClass(this.toolbarEles["insertUnorderedList"], "twbbsEditorButtonSelected").exec('insertUnorderedList', '').processButtonStatus(["insertUnorderedList"]);
        }
        else {
            this._getRange().insertUbbCode("[list][*]" + this.selectText + "[/*][/list]", -11)._emptyRange();
        }
        
        this.preventDefault(e);
    },
    
    strikeThroughHandler: function(e){
        e = e || window.event;
        
        if (this.isDesign) {
            var filter = ["strikeThrough"];
            this.toggleClass(this.toolbarEles["strikeThrough"], "twbbsEditorButtonSelected").exec('strikeThrough', '').processButtonStatus(["strikeThrough"]);
        }
        else {
            this._getRange().insertUbb("s")._emptyRange();
        }
        
        this.preventDefault(e);
    },
    
    insertHorizontalLineShowHandler: function(e){
        e = e || window.event;
        var height = 100;
        var width = 200;
        var me = this;
        var html = [];
        var target = e.target || e.srcElement;
        html.push("<p>請輸入水平線的寬度：<br />");
        html.push('<input type="text" value="100%" id="twbbsEditorHLWidth" /></p>');
        this._getRange();
        var confrimHandler = function(e){
            e = e || window.event;
            me.insertHorizontalLineHandler.call(me, [e, height]);
            me.closeWin().preventDefault(e)._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin()._emptyRange();
        };
        this.displayWin(target, html.join(""), width, confrimHandler, cancleHandler, "twbbsEditorHLWidth").preventDefault(e);
    },
    
    insertHorizontalLineHandler: function(e){
        e = e || window.event;
        var width = this.$("twbbsEditorHLWidth").value;
        if (!/^\d+%$/.test(width)) {
            width = parseInt(width);
            if (!width || isNaN(width)) {
                width = "100%";
            }
        }
        if (this.isDesign) {
            var html = ['<hr width="', width, '" />'];
            this.insertHtml(html.join(""));
        }
        else {
            this.insertUbbCode("[hr=1," + width + ",left,#000000][/hr]");
        }
        
        this.preventDefault(e);
    },
    
    insertTableShowHandler: function(e){
        e = e || window.event;
        var height = 90;
        var width = 200;
        var me = this;
        var html = [];
        var target = e.target || e.srcElement;
        html.push("<p>請輸入下列參數：<br />");
        html.push('<label>行數<input type="text" id="twbbsEditorTableCols" value="2" maxlength="3" style="width:20px;" /> </label>');
        html.push('<label>列數<input type="text" id="twbbsEditorTableRows" value="2" maxlength="3" style="width:20px;" /> </label>');
        html.push('<label>寬度<input type="text" id="twbbsEditorTableWidth" value="50%" style="width:25px;" /> </label></p>');
        this._getRange();
        var confrimHandler = function(e){
            e = e || window.event;
            me.insertTableHandler.call(me, e);
            me._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin();
            me._emptyRange();
        };
        this.displayWin(target, html.join(""), width, confrimHandler, cancleHandler, "twbbsEditorTableCols").preventDefault(e);
    },
    
    insertTableHandler: function(e){
        e = e || window.event;
        var cols = parseInt(this.$("twbbsEditorTableCols").value) || 2;
        var rows = parseInt(this.$("twbbsEditorTableRows").value) || 2;
        var width = this.$("twbbsEditorTableWidth").value;
        if (/^\d+%$/.test(width)) {
            if (!/^\d{1,2}%$/.test(width)) {
                width = "99%";
            }
        }
        else 
            if (/^\d+$/.test(parseInt(width))) {
                if (!/^\d{1,3}$/.test(parseInt(width))) {
                    width = 999;
                }
                else {
                    width = parseInt(width);
                }
            }
            else {
                width = "50%";
            }
        var html = ['<table border="0" bgcolor="#EEEEEE" cellpadding="0" cellspacing="0" style="border-top:1px solid #000000;border-left:1px solid #000000;" width="', width, '">'];
        var rowsHtml = ['<tr>'];
        while (rows--) {
            rowsHtml.push('<td style="border-right:1px solid #000000;border-bottom:1px solid #000000;">&nbsp;</td>');
        }
        rowsHtml.push('</tr>');
        var rowsHtml = rowsHtml.join("");
        while (cols--) {
            html.push(rowsHtml);
        }
        html.push('</table>');
        if (this.isDesign) {
            this.insertHtml(html.join(""));
        }
        else {
            var nodeList = this.html2dom(html.join(""));
            var ubb = this.dom2ubb(nodeList[0]);
            this.insertUbbCode(ubb);
        }
        
        this.closeWin().preventDefault(e);
    },
    
    insertMusicShowHandler: function(e){
        e = e || window.event;
        var height = 100;
        var width = 205;
        var me = this;
        var html = [];
        var target = e.target || e.srcElement;
        html.push("<p>請輸入音像連結的網址：<br />");
        html.push('<input type="text" value="http://" id="twbbsEditorMusicURL" /><br /><span style="color:#999999;font-size:11px;">例如:http://twbbs.net.tw/music.mp3</span></p>');
        this._getRange();
        var confrimHandler = function(e){
            e = e || window.event;
            me.insertMusicHandler.call(me, e);
            me._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin();
            me._emptyRange();
        };
        this.displayWin(target, html.join(""), width, confrimHandler, cancleHandler, "twbbsEditorMusicURL");
        this.preventDefault(e);
    },
    
    insertMusicHandler: function(e){
        e = e || window.event;
        
        var url = this.$("twbbsEditorMusicURL").value;
        if (url != '' && !/^http:\/\/$/i.test(url)) {
            if (!/^http:\/\//i.test(url)) {
                url = "http://" + url;
            }
            var html = ['<img class="tw_music" src="', TWBBS_EDITOR_ROOT + "images/spacer.gif", '" style="width: 200px; height: 40px;" alt="', url, '" title="', url, '" />'];
            if (this.isDesign) {
                this.insertHtml(html.join(""));
            }
            else {
                var nodeList = this.html2dom(html.join(""));
                var ubb = this.dom2ubb(nodeList[0]);
                this.insertUbbCode(ubb);
            }
        }
        
        this.closeWin().preventDefault(e);
    },
    
    insertQuoteShowHandler: function(e){
        e = e || window.event;
        var height = 220;
        var width = 265;
        var me = this;
        var html = [];
        var target = e.target || e.srcElement;
        html.push("請輸入要引用的文本：");
        html.push('<table border="0">');
        html.push('<tr><th><label>作者：</label></th><td><input type="text" value="" id="twbbsEditorQuoteAuthor" /></td></tr>');
        html.push('<tr><th><label>日期：</label></th><td><input type="text" value="" id="twbbsEditorQuoteDate" /></td></tr>');
        html.push('<tr><th><label>內容：</label></th><td><textarea type="text" value="" id="twbbsEditorQuoteText" style="width:180px;height:100px;" ></textarea></td></tr>');
        html.push('</table>');
        this._getRange();
        var confrimHandler = function(e){
            e = e || window.event;
            me.insertQuoteHandler.call(me, e);
            me._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin()._emptyRange();
        };
        this.displayWin(target, html.join(""), width, confrimHandler, cancleHandler, "twbbsEditorQuoteAuthor").preventDefault(e);
    },
    
    insertQuoteHandler: function(e){
        e = e || window.event;
        var author = this.$("twbbsEditorQuoteAuthor").value;
        var date = this.$("twbbsEditorQuoteDate").value;
        var text = this.$("twbbsEditorQuoteText").value;
        var html = [];
        if (!/^\s*$/.test(text)) {
            html.push('<blockquote>QUOTE:<hr/>');
            html.push('<i>');
            if (!/^\s*$/.test(author) || !/^\s*$/.test(date)) {
                if (!/^\s*$/.test(author)) {
                    html.push("作者：" + author + " ");
                }
                if (!/^\s*$/.test(date)) {
                    html.push("回覆日期：" + date);
                }
            }
            html.push('</i><br /><strong>');
            html.push(text);
            html.push('</strong><hr />');
            html.push('</blockquote><br />');
            
            if (this.isDesign) {
                this.insertHtml(html.join(""));
            }
            else {
                var nodeList = this.html2dom(html.join(""));
                var ubb = this.dom2ubb(nodeList[0]);
                this.insertUbbCode(ubb);
            }
        }
        
        this.closeWin().preventDefault(e);
    },
    
    insertFlashShowHandler: function(e){
        e = e || window.event;
        var height = 100;
        var width = 220;
        var me = this;
        var html = [];
        var target = e.target || e.srcElement;
        html.push("<p>請輸入Flash連結的網址：<br />");
        html.push('<input type="text" value="http://" id="twbbsEditorFlashURL" /><br /><span style="color:#999999;font-size:11px;">例如:http://twbbs.net.tw/flash.swf</span>');
        html.push('<br /><label>寬度:<input type="text" id="twbbsEditorFlashWidth" size="3" value="auto" /></label>&nbsp;<label>高度:<input type="text" id="twbbsEditorFlashHeight" size="3" value="auto" /></label></p>');
        this._getRange();
        var confrimHandler = function(e){
            e = e || window.event;
            me.insertFlashHandler.call(me, e);
            me.closeWin()._emptyRange();
        };
        var cancleHandler = function(e){
            e = e || window.event;
            me.closeWin()._emptyRange();
        };
        this.displayWin(target, html.join(""), width, confrimHandler, cancleHandler, "twbbsEditorFlashURL").preventDefault(e);
    },
    
    insertFlashHandler: function(e){
        var url = this.$("twbbsEditorFlashURL").value;
        var width = parseInt(this.$("twbbsEditorFlashWidth").value);
        var height = parseInt(this.$("twbbsEditorFlashHeight").value);
        if (url != '' && !/^http:\/\/$/i.test(url)) {
            if (!/^http:\/\//i.test(url)) {
                url = "http://" + url;
            }
            var w = width || 50;
            var h = width || 50;
            var html = ['<img class="tw_flash" src="', TWBBS_EDITOR_ROOT + "images/spacer.gif", '" style="width: ', width, 'px; height: ', height, 'px;" alt="', url, '" title="', url, '" width="', w, '" height="', h, '" />'];
            if (this.isDesign) {
                this.insertHtml(html.join(""));
            }
            else {
                var nodeList = this.html2dom(html.join(""));
                var ubb = this.dom2ubb(nodeList[0]);
                this.insertUbbCode(ubb);
            }
        }
        this.closeWin().preventDefault(e);
    }
};

function twbbseditorReady(f){
    twbbseditorReady.bindReady();
    
    if (twbbseditorReady.isReady) {
        f();
    }
    else {
        twbbseditorReady.readyList.push(f);
    }
}

twbbseditorReady.isReady = false;
twbbseditorReady.readyBound = false;
twbbseditorReady.readyList = new Array();
twbbseditorReady.userAgent = navigator.userAgent.toLowerCase();
twbbseditorReady.browser = {
    version: (twbbseditorReady.userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
    safari: /webkit/.test(twbbseditorReady.userAgent),
    opera: /opera/.test(twbbseditorReady.userAgent),
    msie: /msie/.test(twbbseditorReady.userAgent) && !/opera/.test(twbbseditorReady.userAgent),
    mozilla: /mozilla/.test(twbbseditorReady.userAgent) && !/(compatible|webkit)/.test(twbbseditorReady.userAgent)
};

twbbseditorReady.execute = function(){
    if (twbbseditorReady.isReady) {
        return;
    }
    var len = twbbseditorReady.readyList.length;
    for (var n = 0; n < len; n++) {
        twbbseditorReady.readyList[n]();
    }
    
    twbbseditorReady.readyList = null;
    
    if (twbbseditorReady.browser.mozilla || twbbseditorReady.browser.opera) 
        document.removeEventListener("DOMContentLoaded", twbbseditorReady.execute, false);
    
    twbbseditorReady.isReady = true;
};

twbbseditorReady.bindReady = function(){
    if (twbbseditorReady.readyBound) {
        return;
    }
    twbbseditorReady.readyBound = true;
    
    if (twbbseditorReady.browser.mozilla || twbbseditorReady.browser.opera) 
        document.addEventListener("DOMContentLoaded", twbbseditorReady.execute, false);
    
    else 
        if (twbbseditorReady.browser.msie) {
            document.write("<scr" + "ipt id=__ie_init defer=true " +
            "src=//:><\/script>");
            
            var script = document.getElementById("__ie_init");
            
            if (script) 
                script.onreadystatechange = function(){
                    if (this.readyState != "complete") 
                        return;
                    twbbseditorReady.execute();
                };
            
            script = null;
        }
        else 
            if (twbbseditorReady.browser.safari) 
                twbbseditorReady.safariTimer = setInterval(function(){
                    if (document.readyState == "loaded" ||
                    document.readyState == "complete") {
                    
                        clearInterval(ready.safariTimer);
                        twbbseditorReady.safariTimer = null;
                        
                        twbbseditorReady.execute();
                    }
                }, 10);
    
    if (typeof window.addEventListener == "function") {
        window.addEventListener("load", twbbseditorReady.execute, false);
    }
    else 
        if (typeof window.attacheEvent == "function") {
            window.attacheEvent("onload", twbbseditorReady.execute);
        }
};

